У меня есть массив:
[1, 2, 3, 5, 2, 8, 9, 2]
Я хотел бы знать, сколько 2
s в массиве.
Каков самый элегантный способ сделать это в JavaScript без зацикливания с for
циклом?
javascript
Лим
источник
источник
const count = countItems(array, 2);
детали реализации можно обсуждать внутри.[ этот ответ немного устарел: читайте правки ]
Передай привет своим друзьям:
map
иfilter
иreduce
иforEach
иevery
т. Д.(Я только иногда пишу for-loop в javascript, поскольку отсутствует область видимости на уровне блоков, поэтому вам все равно придется использовать функцию в качестве тела цикла, если вам нужно захватить или клонировать ваш итерационный индекс или значение. For-loops в целом более эффективны, но иногда требуется закрытие.)
Самый читаемый способ:
(Мы могли бы написать
.filter(function(x){return x==2}).length
вместо)Ниже приведено более эффективное использование пространства (O (1), а не O (N)), но я не уверен, сколько из выгоды / штрафа вы могли бы заплатить с точки зрения времени (не более чем постоянный фактор, так как вы посещаете каждый элемент ровно один раз):
(Если вам нужно оптимизировать этот конкретный фрагмент кода, цикл for может быть быстрее в некоторых браузерах ... вы можете протестировать его на jsperf.com.)
Затем вы можете быть элегантным и превратить его в функцию-прототип:
Как это:
Вы также можете вставить обычный старый метод for-loop (см. Другие ответы) в приведенное выше определение свойства (опять же, это, вероятно, будет намного быстрее).
2017 редактировать :
К сожалению, этот ответ стал более популярным, чем правильный ответ. На самом деле, просто используйте принятый ответ. Хотя этот ответ может быть симпатичным, компиляторы js, вероятно, не (или не могут из-за спецификации) оптимизировать такие случаи. Таким образом, вы должны написать простой цикл:
Вы можете определить версию, в
.countStrictEq(...)
которой используется===
понятие равенства. Понятие равенства может быть важно для того, что вы делаете! (например[1,10,3,'10'].count(10)==2
, потому что числа типа «4» == 4 в javascript ... следовательно, вызывая его.countEq
или.countNonstrict
подчеркивая, он использует==
оператор.)Также рассмотрите возможность использования вашей собственной многосетевой структуры данных (например, типа «питона
collections.Counter
»), чтобы избежать необходимости делать подсчет в первую очередь.Демо-версия:
sidenote: Хотя, если вы все еще хотите использовать функциональное программирование (или одноразовую однострочную компоновку без переопределения Array.prototype), вы можете написать ее более кратко в наши дни как
[...].filter(x => x==2).length
. Если вы заботитесь о производительности, обратите внимание, что, хотя это асимптотически та же производительность, что и цикл for (O (N) время), может потребоваться O (N) дополнительная память (вместо O (1) памяти), поскольку она почти конечно, создайте промежуточный массив и затем посчитайте элементы этого промежуточного массива.источник
array.reduce(function(total,x){return x==value? : total+1 : total}, 0)
[...].reduce(function(total,x){return x==2 ? total+1 : total}, 0)
const count = (list) => list.filter((x) => x == 2).length
. Затем используйте его, позвонив,count(list)
где list это массив чисел. Вы такжеconst count = (list) => list.filter((x) => x.someProp === 'crazyValue').length
можете подсчитать количество экземпляров crazyValue в массиве объектов. Обратите внимание, это точное соответствие для свойства.ES6 Обновление до JS:
Обратите внимание, что вы всегда должны использовать тройные равенства:
===
чтобы получить правильное сравнение:Следующая единственная функция Arrow (лямбда-функция) в JS:
может быть упрощено до этой краткой формы для одного ввода:
где
return
подразумевается.источник
2017: Если кто-то все еще интересуется этим вопросом, мое решение заключается в следующем:
источник
Если вы используете lodash или подчеркивание, то метод _.countBy предоставит объект совокупных итогов, определяемый каждым значением в массиве. Вы можете превратить это в однострочник, если вам нужно только посчитать одно значение:
Это также хорошо работает на массивах чисел. Однострочником для вашего примера будет:
источник
Самый странный способ, которым я могу думать, это:
Куда:
Мое предложение, используйте время или для цикла ;-)
источник
Отсутствие цикла обычно означает передачу процесса какому-либо методу, который использует цикл.
Вот способ, которым наш кодовый ненавидящий кодер может удовлетворить его отвращение по цене:
Вы также можете повторно вызывать indexOf, если он доступен как метод массива, и каждый раз перемещать указатель поиска.
Это не создает новый массив, и цикл выполняется быстрее, чем forEach или фильтр.
Это может иметь значение, если у вас есть миллион членов, чтобы посмотреть.
источник
String(a).match(/2/g).length + 1
- хотя остерегайтесь этого, иначе ваша реализация не будет хорошо работать с двузначными числами.Большинство опубликованных решений, использующих функции массива, такие как фильтр, являются неполными, поскольку они не параметризованы.
Здесь идет решение, с помощью которого элемент для подсчета может быть установлен во время выполнения.
Преимущество этого подхода заключается в том, что он может легко изменить функцию, чтобы подсчитать, например, количество элементов больше X.
Вы также можете объявить функцию приведения встроенной
источник
var elementToFind=2; ... function (elementToFind, total, number){ return total += number==elementToFind; }.bind(this, elementToFind) ...
труднее читать и не дает никаких преимуществ по сравнению с просто... (acc, x) => acc += number == 2...
. Мне нравится ваше использование+=
вместо,acc + (number == 2)
хотя. Похоже, необоснованный синтаксис HACK, хотя.Действительно, зачем тебе это
map
илиfilter
для этого?reduce
был «рожден» для таких операций:[1, 2, 3, 5, 2, 8, 9, 2].reduce( (count,2)=>count+(item==val), 0);
Это оно! (если
item==val
в каждой итерации к аккумулятору будет добавлено 1count
, какtrue
будет разрешено1
).Как функция:
Или продолжайте расширять свои массивы:
источник
Лучше обернуть это в функцию:
источник
Вот ES2017 + способ получить количество для всех элементов массива в O (N):
Вы также можете при желании отсортировать вывод:
console.log (countsSorted) для вашего примера массива:
источник
Я считаю, что вы ищете, это функциональный подход
elem === 'a' - это условие, замените его своим.
источник
count = arr.filter(elem => elem === 'a').length
илиcount = arr.filter(elem => {return elem === 'a'}).length
Я начинающий фанат функции снижения массива js.
На самом деле, если вы действительно хотите проявить фантазию, вы можете создать функцию count для прототипа Array. Тогда вы можете использовать его повторно.
Тогда делай
источник
Решение рекурсией
источник
filter
,reduce
или простойforLoop
, а также более дорогой, если смотреть на производительность, но все же отличный способ сделать это с помощью рекурсии. Мое единственное изменение: я просто думаю, что было бы лучше создать функцию и добавить в нее фильтр, чтобы скопировать массив и избежать мутации исходного массива, а затем использовать рекурсив в качестве внутренней функции.Я бы сделал что-то подобное:
источник
Создайте новый метод для класса Array в файле уровня ядра и используйте его во всем проекте.
Используйте это где угодно в вашем проекте -
источник
Вот один вкладыш в JavaScript.
(v === 2)
в массиве, возвращая массив единиц и нулей.Результат есть
3
.источник
В зависимости от того, как вы хотите его запустить:
источник
Вы можете использовать свойство length в массиве JavaScript:
источник