Подтвердить что ты не робот

Как подсчитать количество определенного элемента в массиве?

Если у меня есть массив [1, 2, 3, 5, 2, 8, 9, 2], я хотел бы проверить, сколько 2 есть в массиве. Какой самый элегантный способ сделать это в JavaScript без цикла с циклом for?

4b9b3361

Ответ 1

Очень просто:

var count = 0;
for(var i = 0; i < array.length; ++i){
    if(array[i] == 2)
        count++;
}

Ответ 2

[этот ответ немного устарел: читайте правки]

Скажи привет друзьям: map и filter и reduce и forEach и every т.д.

(Я только иногда пишу for-loop в javascript, потому что отсутствует область видимости на уровне блоков, поэтому вам все равно придется использовать функцию в качестве тела цикла, если вам нужно захватить или клонировать ваш итерационный индекс или значение. For-loops в целом более эффективны, но иногда требуется закрытие.)

Самый читаемый способ:

[....].filter(x => x==2).length

(Мы могли бы написать .filter(function(x){return x==2}).length Вместо этого)

Следующее является более экономичным (O (1), а не O (N)), но я не уверен, какую выгоду/штраф вы могли бы заплатить с точки зрения времени (не более чем постоянный фактор, так как вы посещаете каждый элемент ровно один раз):

[....].reduce((total,x) => (x==2 ? total+1 : total), 0)

(Если вам нужно оптимизировать этот конкретный фрагмент кода, цикл for может быть быстрее в некоторых браузерах... вы можете проверить это на jsperf.com.)


Затем вы можете быть элегантным и превратить его в функцию-прототип:

[1, 2, 3, 5, 2, 8, 9, 2].count(2)

Как это:

Object.defineProperties(Array.prototype, {
    count: {
        value: function(value) {
            return this.filter(x => x==value).length;
        }
    }
});

Вы также можете вставить обычный старый метод for-loop (см. Другие ответы) в приведенное выше определение свойства (опять же, это, вероятно, будет гораздо быстрее).


2017 редактировать:

К сожалению, этот ответ стал более популярным, чем правильный ответ. На самом деле, просто используйте принятый ответ. Хотя этот ответ может быть симпатичным, компиляторы js, вероятно, не (или не могут из-за спецификаций) оптимизировать такие случаи. Таким образом, вы должны написать простой цикл for:

Object.defineProperties(Array.prototype, {
    count: {
        value: function(query) {
            /* 
               Counts number of occurrences of query in array, an integer >= 0 
               Uses the javascript == notion of equality.
            */
            var count = 0;
            for(let i=0; i<this.length; i++)
                if (this[i]==query)
                    count++;
            return count;
        }
    }
});

Вы можете определить версию .countStrictEq(...) которая использует === понятие равенства. Понятие равенства может быть важно для того, что вы делаете! (например, [1,10,3,'10'].count(10)==2, потому что числа типа "4" == 4 в javascript... следовательно, называя его .countEq или .countNonstrict подчеркивает, что использует == оператор.)

Также рассмотрите возможность использования вашей собственной многосетевой структуры данных (например, как python ' collections.Counter '), чтобы избежать необходимости делать подсчет в первую очередь.

class Multiset extends Map {
    constructor(...args) {
        super(...args);
    }
    add(elem) {
        if (!this.has(elem))
            this.set(elem, 1);
        else
            this.set(elem, this.get(elem)+1);
    }
    remove(elem) {
        var count = this.has(elem) ? this.get(elem) : 0;
        if (count>1) {
            this.set(elem, count-1);
        } else if (count==1) {
            this.delete(elem);
        } else if (count==0)
            throw 'tried to remove element ${elem} of type ${typeof elem} from Multiset, but does not exist in Multiset (count is 0 and cannot go negative)';
            // alternatively do nothing {}
    }
}

Демо-версия:

> counts = new Multiset([['a',1],['b',3]])
Map(2) {"a" => 1, "b" => 3}

> counts.add('c')
> counts
Map(3) {"a" => 1, "b" => 3, "c" => 1}

> counts.remove('a')
> counts
Map(2) {"b" => 3, "c" => 1}

> counts.remove('a')
Uncaught tried to remove element a of type string from Multiset, but does not exist in Multiset (count is 0 and cannot go negative)

sidenote: Хотя, если вы все еще хотели использовать функциональное программирование (или одноразовую однострочную компоновку без переопределения Array.prototype), вы можете написать ее более кратко в настоящее время как [...].filter(x => x==2).length Если вы заботитесь о производительности, обратите внимание, что хотя она асимптотически совпадает с производительностью цикла for (O (N)), может потребоваться дополнительная память O (N) (вместо памяти O (1)), поскольку она почти конечно, создать промежуточный массив, а затем подсчитать элементы этого промежуточного массива.

Ответ 3

2017 Если кто-то все еще интересуется вопросом, мое решение следующее:

const arrayToCount = [1, 2, 3, 5, 2, 8, 9, 2];
const result = arrayToCount.filter(i => i === 2).length;
console.log('number of the found elements: ' + result);

Ответ 4

ES6 Обновление до JS:

// Let has local scope
let array = [1, 2, 3, 5, 2, 8, 9, 2]

// Functional filter with an Arrow function
array.filter(x => x === 2).length  // -> 3

Следующая единодушная функция стрелки (лямбда-функция) в JS:

(x) => {
   const k = 2
   return k * x
}

может быть упрощено до этой краткой формы для одного ввода:

x => 2 * x

где подразумевается return.

Ответ 5

Если вы используете lodash или подчеркивание, метод _. countBy предоставит объект совокупных итогов, определяемых каждым значением в массиве. Вы можете превратить его в однострочный, если вам нужно только подсчитать одно значение:

_.countBy(['foo', 'foo', 'bar'])['foo']; // 2

Это также отлично работает с массивами чисел. Однострочный для вашего примера будет:

_.countBy([1, 2, 3, 5, 2, 8, 9, 2])[2]; // 3

Ответ 6

Самый странный способ, который я могу сделать, это:

(a.length-(' '+a.join(' ')+' ').split(' '+n+' ').join(' ').match(/ /g).length)+1

Где:

  • a - это массив
  • n - количество, которое нужно подсчитать в массиве

Мое предложение, используйте while или для цикла; -)

Ответ 7

Не использовать цикл, как правило, означает передачу процесса некоторому методу, в котором использует цикл.

Вот способ, которым наш ненавязчивый кодер может удовлетворить его отвращение по цене:

var a=[1, 2, 3, 5, 2, 8, 9, 2];

alert(String(a).replace(/[^2]+/g,'').length);


/*  returned value: (Number)
3
*/

Вы также можете повторно вызвать indexOf, если он доступен как метод массива, и каждый раз перемещать указатель поиска.

Это не создает новый массив, и цикл работает быстрее, чем forEach или filter.

Это может иметь значение, если у вас есть миллион участников, чтобы посмотреть.

function countItems(arr, what){
    var count= 0, i;
    while((i= arr.indexOf(what, i))!= -1){
        ++count;
        ++i;
    }
    return count
}

countItems(a,2)

/*  returned value: (Number)
3
*/

Ответ 8

Действительно, зачем вам map или filter для этого? reduce было "рождено" для таких операций:

[1, 2, 3, 5, 2, 8, 9, 2].reduce( (count,2)=>count+(item==val), 0);

это! (если item==val в каждой итерации, а затем 1 будет добавлен в накопительном count, так как true будет решать 1).

Как функция:

function countInArray(arr, val) {
   return arr.reduce((count,item)=>count+(item==val),0)
}

Или продолжайте расширять свои массивы:

Array.prototype.count = function(val) {
   return this.reduce((count,item)=>count+(item==val),0)
}

Ответ 9

Большинство размещенных решений с использованием функций массива, таких как фильтр, являются неполными, поскольку они не параметризируются.

Здесь представлено решение, с помощью которого элемент для подсчета может быть установлен во время выполнения.

function elementsCount(elementToFind, total, number){
    return total += number==elementToFind;
}

var ar = [1, 2, 3, 5, 2, 8, 9, 2];
var elementToFind=2;
var result = ar.reduce(elementsCount.bind(this, elementToFind), 0);

Преимущество этого подхода заключается в том, что можно легко изменить функцию для подсчета, например, количества элементов, больших X.

Вы также можете объявить функцию сокращения inline

var ar = [1, 2, 3, 5, 2, 8, 9, 2];
var elementToFind=2;
var result = ar.reduce(function (elementToFind, total, number){
    return total += number==elementToFind;
}.bind(this, elementToFind), 0);

Ответ 10

Я начинающий поклонник функции уменьшения массива JS.

const myArray =[1, 2, 3, 5, 2, 8, 9, 2];
const count = myArray.reduce((count, num) => num === 2 ? count + 1 : count, 0)

На самом деле, если вы действительно хотите проявить фантазию, вы можете создать функцию count в прототипе Array. Тогда вы можете использовать его повторно.

Array.prototype.count = function(filterMethod) {
  return this.reduce((count, item) => filterMethod(item)? count + 1 : count, 0);
} 

Тогда делай

const myArray =[1, 2, 3, 5, 2, 8, 9, 2]
const count = myArray.count(x => x==2)

Ответ 11

var arrayCount = [1,2,3,2,5,6,2,8];
var co = 0;
function findElement(){
    arrayCount.find(function(value, index) {
      if(value == 2)
        co++;
    });
    console.log( 'found' + ' ' + co + ' element with value 2');
}

Ответ 12

Создайте новый метод для класса Array в файле уровня ядра и используйте его во всем проекте.

// say in app.js
Array.prototype.occurrence = function(val) {
  return this.filter(e => e === val).length;
}

Используйте это где угодно в вашем проекте -

[1, 2, 4, 5, 2, 7, 2, 9].occurrence(2);
// above line returns 3

Ответ 13

Вот один вкладыш в JavaScript.

  1. Используйте карту. Найдите совпадающие значения (v === 2) в массиве, возвращая массив единиц и нулей.
  2. Используйте Уменьшить. Добавьте все значения массива для общего числа найденных.
[1, 2, 3, 5, 2, 8, 9, 2]
  .map(function(v) {
    return v === 2 ? 1 : 0;
  })
  .reduce((a, b) => a + b, 0);

Результат 3.

Ответ 14

Я считаю, что вы ищете, это функциональный подход

    const arr = ['a', 'a', 'b', 'g', 'a', 'e'];
    const count = arr.filter(elem => elem === 'a').length;
    console.log(count); // Prints 3

elem === 'a' - это условие, замените его своим.

Ответ 15

Решение путем рекурсии

function count(arr, value) {
   if (arr.length === 1)    {
      return arr[0] === value ? 1 : 0;
   } else {
      return (arr.shift() === value ? 1 : 0) + count(arr, value);
   }
}

count([1,2,2,3,4,5,2], 2); // 3

Ответ 16

Вы можете использовать свойство length в массиве JavaScript:

var myarray = [];
var count = myarray.length;//return 0

myarray = [1,2];
count = myarray.length;//return 2