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

2020/10/24 08:42 · javascript ·  · 0评论

我有一个数组:

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

我想知道2数组中有多少个

在JavaScript中不使用循环循环的最优雅的方法是什么for

很简单:

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

[这个答案有点过时:请阅读编辑内容]

问好你的朋友:mapfilterreduceforEachevery等。

(由于缺少块级作用域,我偶尔只用javascript写for循环,因此,如果您需要捕获或克隆迭代索引或值,则无论如何都必须使用函数作为循环的主体。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循环技术(请参阅其他答案)保留在上述属性定义中(同样,这可能会更快)。


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强调它使用==运算符。)

也可以考虑使用自己的多集数据结构(例如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循环(O(N)时间)渐近相同,但它可能需要O(N)额外的内存(而不是O(1)内存),因为它将几乎当然会生成一个中间数组,然后计算该中间数组的元素。

ES6更新到JS:

请注意,===在JavaScript中进行比较时,您应始终使用三等号

// 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

JavaScript中的以下匿名Arrow函数(lambda函数):

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

对于单个输入,可以简化为以下简洁形式:

x => 2 * x

其中return的暗示。

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

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

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

这在数字数组上也很好用。您的示例的一线是:

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

我想到的最奇怪的方式是:

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

哪里:

  • 一个是数组
  • n是要在数组中计数的数字

我的建议,使用一会儿或for循环;-)

不使用循环通常意味着将流程移交给某些确实使用循环的方法。

这是我们的循环讨厌编码器可以满足他的厌恶要求的一种方式:

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

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


/*  returned value: (Number)
3
*/

您也可以重复调用indexOf(如果它可用作数组方法),并每次都移动搜索指针。

这不会创建新的数组,并且循环比forEach或filter更快。

如果您有100万会员,这可能会有所作为。

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
*/

这是一种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 ]
]

大多数发布的使用数组函数(如filter)的解决方案都不完整,因为它们没有参数化。

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

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的元素数量进行计数。

您也可以内联声明reduce函数

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

真的,您为什么需要mapfilter为此?
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)
}

我是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)

最好将其包装为函数:

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

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

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

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

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

递归求解

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

我会做这样的事情:

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

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

  console.log(dd);
}

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

这是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

根据您要如何运行它:

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, …}

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

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

myarray = [1,2];
count = myarray.length;//return 2
本文地址:http://javascript.askforanswer.com/ruhejisuanshuzuzhongdemouxieyuansu.html
文章标签:
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!