如何计算数组中某些元素的数量?

时间:2011-05-25 07:26:45

标签: javascript

如果我有一个数组[1, 2, 3, 5, 2, 8, 9, 2],我想查看数组中有多少2个。在没有使用for循环循环的情况下,在JavaScript中执行此操作的最优雅方法是什么?

22 个答案:

答案 0 :(得分:198)

[这个答案有点过时了:阅读编辑]

向你的朋友问好:mapfilter以及reduceforEach以及every等。

(我偶尔会在javascript中编写for循环,因为缺少块级范围,所以如果你需要捕获或克隆你的迭代索引或值,你必须使用一个函数作为循环体。 For循环通常更有效,但有时你需要一个闭包。)

最易读的方式:

[...].filter(function(x){return x==2}).length

以下更节省空间(O(1)而不是O(N)),但我不确定您可以在时间方面支付多少利益/罚款(不超过常数因素)因为你只访问每个元素一次):

[...].reduce(function(total,x){return 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.reduce(...);
        }
    }
});

你也可以在上面的属性定义中坚持常规的旧for循环技术(参见其他答案)(同样,这可能会更快)。


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,因为javascript中的数字类似'4'== 4 ...因此称之为.countEq.countNonstrict强调它使用==运算符。)< / p>

还要考虑使用您自己的多集数据结构(例如像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)

旁注:但是,如果你仍然想要功能编程方式(或者不重写Array.prototype的一次性单行程),你现在可以更加简洁地编写它[...].filter(x => x==2).length。如果你关心性能,请注意虽然这是渐进式的与for-loop(O(N)时间)相同的性能,但它可能需要O(N)额外的内存(而不是O(1)内存),因为它几乎会当然会生成一个中间数组,然后计算该中间数组的元素。

答案 1 :(得分:60)

很简单:

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

答案 2 :(得分:47)

<强> 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);

答案 3 :(得分:29)

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中的以下一致箭头函数(lambda函数):

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

可以简化为单一输入的简洁形式:

x => 2 * x

暗示return

答案 4 :(得分:7)

如果使用lodash或下划线,_.countBy方法将提供由数组中每个值键入的聚合总计对象。如果您只需要计算一个值,则可以将其转换为单行:

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

这也适用于数字数组。你的例子的单行将是:

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

答案 5 :(得分:4)

这是一种ES2017 +方法,用于获取O(N)中所有数组项的计数:

const arr = [1, 2, 3, 5, 2, 8, 9, 2];
const counts = {};

arr.forEach((el) => {
  counts[el] = counts[el] ? (counts[el] += 1) : 1;
});

您还可以选择对输出进行排序:

const countsSorted = Object.entries(counts).sort(([_, a], [__, b]) => a - b);

console.log(countsSorted)用于示例数组:

[
  [ '2', 3 ],
  [ '1', 1 ],
  [ '3', 1 ],
  [ '5', 1 ],
  [ '8', 1 ],
  [ '9', 1 ]
]

答案 6 :(得分:3)

我能想到的最奇怪的方法是:

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

其中:

  • a 是数组
  • n 是要在数组中计算的数字

我的建议,使用while或for循环; - )

答案 7 :(得分:2)

不使用循环通常意味着将过程交给 使用循环的某种方法。

这是一种我们的循环仇恨编码器可以满足他的厌恶的方式,价格:

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

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


/*  returned value: (Number)
3
*/

如果可以作为数组方法使用,也可以重复调用indexOf,并且每次都移动搜索指针。

这不会创建新数组,并且循环比forEach或过滤器快。

如果您有一百万名成员可以查看,那可能会有所不同。

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 :(得分:2)

最好将其包装为函数:

let countNumber = (array,specificNumber) => {
    return array.filter(n => n == specificNumber).length
}

countNumber([1,2,3,4,5],3) // returns 1

答案 9 :(得分:1)

大多数使用过滤器等数组函数的已发布解决方案都不完整,因为它们没有参数化。

这是一个解决方案,可以在运行时设置要计数的元素。

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的元素数。

您也可以声明内联缩小功能

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 :(得分:1)

Array.prototype.count = function (v) {
    var c = 0;
    for (let i = 0; i < this.length; i++) {
        if(this[i] == v){
            c++;
        }
    }
    return c;
}

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

console.log(arr.count(2)); //3

答案 11 :(得分:0)

另一种使用 RegExp

的方法

const list = [1, 2, 3, 5, 2, 8, 9, 2]
const d = 2;
const counter = (`${list.join()},`.match(new RegExp(`${d}\\,`, 'g')) || []).length

console.log(counter)

步骤如下

  1. 使用逗号连接字符串连接后记得附加',',以免匹配的值在数组末尾时出现错误值
  2. 匹配数字和逗号之间的组合出现的次数
  3. 获取匹配项的长度

答案 12 :(得分:0)

取决于您要如何运行它:

const reduced = (array, val) => { // self explanatory
    return array.filter((element) => element === val).length;
}

console.log(reduced([1, 2, 3, 5, 2, 8, 9, 2], 2));

// 3

const reducer = (array) => { // array to set > set.forEach > map.set
    const count = new Map();
    const values = new Set(array);
    values.forEach((element)=> {
        count.set(element, array.filter((arrayElement) => arrayElement === element).length);
    });
    return count;
}
console.log(reducer([1, 2, 3, 5, 2, 8, 9, 2]));

// Map(6) {1 => 1, 2 => 3, 3 => 1, 5 => 1, 8 => 1, …}

答案 13 :(得分:0)

我是js数组的reduce函数的初学者。

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

实际上,如果您真的想花哨的话,可以在Array原型上创建一个count函数。然后,您可以重用它。

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)

答案 14 :(得分:0)

真的,您为什么需要mapfilterreduce因这类操作而“出生”:

[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)
}

答案 15 :(得分:0)

我相信您正在寻找的是功能性方法

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

elem ==='a'是条件,请用您自己的条件替换。

答案 16 :(得分:0)

这是用javascript编写的一行代码。

  1. 使用地图。在数组中找到匹配的值(v === 2),并返回一个由1和0组成的数组。
  2. 使用减少。将数组的所有值加到找到的总数中。
[1, 2, 3, 5, 2, 8, 9, 2]
  .map(function(v) {
    return v === 2 ? 1 : 0;
  })
  .reduce((a, b) => a + b, 0);

结果为3

答案 17 :(得分:0)

在核心级文件中为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

答案 18 :(得分:0)

&#13;
&#13;
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');
}
&#13;
&#13;
&#13;

我会做那样的事情:

&#13;
&#13;
var arrayCount = [1,2,3,4,5,6,7,8];

function countarr(){
  var dd = 0;
  arrayCount.forEach( function(s){
    dd++;
  });

  console.log(dd);
}
&#13;
&#13;
&#13;

答案 19 :(得分:-1)

递归解决方案

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

答案 20 :(得分:-5)

您可以在JavaScript数组中使用length属性:

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

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

答案 21 :(得分:-8)

        @{
            /**/

            var x = from z in Model.ListOfFaculty
                    select z;
        }



        @foreach (var c in x)
        {
            <div class="row">
                <div class="col-lg-3">
                    <label>FacultyName :@c.Name </label>
                </div>
                <div class="col-lg-3">
                    <label>
                        Count :@{
                            var b = from v in Model.ListOfDepartment
                                    where (v.Faculty_id == c.ID)
                                    select v;


                        }
                        @b.Count()
                    </label>
                </div>
            </div>



        }

    </div>