按习惯性查找给定值在数组中的出现次数
Idiomatically find the number of occurrences a given value has in an array
我有一个带有重复值的数组。我想找到任何给定值的出现次数。
例如,如果我有一个定义为这样的数组:var dataset = [2,2,4,2,6,4,7,8];
,我想找到数组中某个值的出现次数。也就是说,程序应该显示,如果我有 3 次出现值 2
,值出现 1 次6
,依此类推。
最惯用/最优雅的方法是什么?
reduce
在这里比filter
更合适,因为它不会构建一个临时数组只是为了计数。
var dataset = [2,2,4,2,6,4,7,8];
var search = 2;
var count = dataset.reduce(function(n, val) {
return n + (val === search);
}, 0);
console.log(count);
在 ES6 中:
let count = dataset.reduce((n, x) => n + (x === search), 0);
请注意,很容易将其扩展为使用自定义匹配谓词,例如,对具有特定属性的对象进行计数:
people = [
{name: 'Mary', gender: 'girl'},
{name: 'Paul', gender: 'boy'},
{name: 'John', gender: 'boy'},
{name: 'Lisa', gender: 'girl'},
{name: 'Bill', gender: 'boy'},
{name: 'Maklatura', gender: 'girl'}
]
var numBoys = people.reduce(function (n, person) {
return n + (person.gender == 'boy');
}, 0);
console.log(numBoys);
在 javascript 中计算所有项目,即制作像 {x:count of xs}
这样的对象很复杂,因为对象键只能是字符串,所以你不能可靠地计算混合类型的数组。不过,以下简单的解决方案在大多数情况下仍然有效:
count = function (ary, classifier) {
classifier = classifier || String;
return ary.reduce(function (counter, item) {
var p = classifier(item);
counter[p] = counter.hasOwnProperty(p) ? counter[p] + 1 : 1;
return counter;
}, {})
};
people = [
{name: 'Mary', gender: 'girl'},
{name: 'Paul', gender: 'boy'},
{name: 'John', gender: 'boy'},
{name: 'Lisa', gender: 'girl'},
{name: 'Bill', gender: 'boy'},
{name: 'Maklatura', gender: 'girl'}
];
// If you don't provide a `classifier` this simply counts different elements:
cc = count([1, 2, 2, 2, 3, 1]);
console.log(cc);
// With a `classifier` you can group elements by specific property:
countByGender = count(people, function (item) {
return item.gender
});
console.log(countByGender);
2017 更新
在 ES6 中,您可以使用 Map
对象可靠地计算任意类型的对象。
class Counter extends Map {
constructor(iter, key=null) {
super();
this.key = key || (x => x);
for (let x of iter) {
this.add(x);
}
}
add(x) {
x = this.key(x);
this.set(x, (this.get(x) || 0) + 1);
}
}
// again, with no classifier just count distinct elements
results = new Counter([1, 2, 3, 1, 2, 3, 1, 2, 2]);
for (let [number, times] of results.entries())
console.log('%s occurs %s times', number, times);
// counting objects
people = [
{name: 'Mary', gender: 'girl'},
{name: 'John', gender: 'boy'},
{name: 'Lisa', gender: 'girl'},
{name: 'Bill', gender: 'boy'},
{name: 'Maklatura', gender: 'girl'}
];
chessChampions = {
2010: people[0],
2012: people[0],
2013: people[2],
2014: people[0],
2015: people[2],
};
results = new Counter(Object.values(chessChampions));
for (let [person, times] of results.entries())
console.log('%s won %s times', person.name, times);
// you can also provide a classifier as in the above
byGender = new Counter(people, x => x.gender);
for (let g of ['boy', 'girl'])
console.log("there are %s %ss", byGender.get(g), g);
Counter
的类型感知实现可能如下所示(打字稿(:
type CounterKey = string | boolean | number;
interface CounterKeyFunc<T> {
(item: T): CounterKey;
}
class Counter<T> extends Map<CounterKey, number> {
key: CounterKeyFunc<T>;
constructor(items: Iterable<T>, key: CounterKeyFunc<T>) {
super();
this.key = key;
for (let it of items) {
this.add(it);
}
}
add(it: T) {
let k = this.key(it);
this.set(k, (this.get(k) || 0) + 1);
}
}
// example:
interface Person {
name: string;
gender: string;
}
let people: Person[] = [
{name: 'Mary', gender: 'girl'},
{name: 'John', gender: 'boy'},
{name: 'Lisa', gender: 'girl'},
{name: 'Bill', gender: 'boy'},
{name: 'Maklatura', gender: 'girl'}
];
let byGender = new Counter(people, (p: Person) => p.gender);
for (let g of ['boy', 'girl'])
console.log("there are %s %ss", byGender.get(g), g);
array.filter(c => c === searchvalue).length;
以下是一次显示所有计数的一种方法:
var dataset = [2, 2, 4, 2, 6, 4, 7, 8];
var counts = {}, i, value;
for (i = 0; i < dataset.length; i++) {
value = dataset[i];
if (typeof counts[value] === "undefined") {
counts[value] = 1;
} else {
counts[value]++;
}
}
console.log(counts);
// Object {
// 2: 3,
// 4: 2,
// 6: 1,
// 7: 1,
// 8: 1
//}
由于使用Array.filter
,浏览器较新
var dataset = [2,2,4,2,6,4,7,8];
var search = 2;
var occurrences = dataset.filter(function(val) {
return val === search;
}).length;
console.log(occurrences); // 3
const dataset = [2,2,4,2,6,4,7,8];
const count = {};
dataset.forEach((el) => {
count[el] = count[el] + 1 || 1
});
console.log(count)
// {
// 2: 3,
// 4: 2,
// 6: 1,
// 7: 1,
// 8: 1
// }
使用正常循环,您可以一致且可靠地找到出现的情况:
const dataset = [2,2,4,2,6,4,7,8];
function getNumMatches(array, valToFind) {
let numMatches = 0;
for (let i = 0, j = array.length; i < j; i += 1) {
if (array[i] === valToFind) {
numMatches += 1;
}
}
return numMatches;
}
alert(getNumMatches(dataset, 2)); // should alert 3
演示:https://jsfiddle.net/a7q9k4uu/
为了使它更通用,该函数可以接受具有自定义逻辑(返回true
/false
(的谓词函数,这将确定最终计数。例如:
const dataset = [2,2,4,2,6,4,7,8];
function getNumMatches(array, predicate) {
let numMatches = 0;
for (let i = 0, j = array.length; i < j; i += 1) {
const current = array[i];
if (predicate(current) === true) {
numMatches += 1;
}
}
return numMatches;
}
const numFound = getNumMatches(dataset, (item) => {
return item === 2;
});
alert(numFound); // should alert 3
演示:https://jsfiddle.net/57en9nar/1/
您可以使用reduce在一行中计算数组中的所有项目。
[].reduce((a,b) => (a[b] = a[b] + 1 || 1) && a, {})
这将生成一个对象,其键是数组中的不同元素,值是数组中元素的出现次数。然后,您可以通过访问对象上的相应键来访问一个或多个计数。
例如,如果您要将上述内容包装在名为 count()
的函数中:
function count(arr) {
return arr.reduce((a,b) => (a[b] = a[b] + 1 || 1) && a, {})
}
count(['example']) // { example: 1 }
count([2,2,4,2,6,4,7,8])[2] // 3
您可以在JavaScript 1.8
中使用array.reduce(callback[, initialValue])
方法
var dataset = [2,2,4,2,6,4,7,8],
dataWithCount = dataset.reduce( function( o , v ) {
if ( ! o[ v ] ) {
o[ v ] = 1 ;
} else {
o[ v ] = o[ v ] + 1;
}
return o ;
}, {} );
// print data with count.
for( var i in dataWithCount ){
console.log( i + 'occured ' + dataWithCount[i] + 'times ' );
}
// find one number
var search = 2,
count = dataWithCount[ search ] || 0;
我发现最终得到一个对象列表更有用,其中包含一个用于计数内容的键和一个用于计数的键:
const data = [2,2,4,2,6,4,7,8]
let counted = []
for (var c of data) {
const alreadyCounted = counted.map(c => c.name)
if (alreadyCounted.includes(c)) {
counted[alreadyCounted.indexOf(c)].count += 1
} else {
counted.push({ 'name': c, 'count': 1})
}
}
console.log(counted)
返回:
[ { name: 2, count: 3 },
{ name: 4, count: 2 },
{ name: 6, count: 1 },
{ name: 7, count: 1 },
{ name: 8, count: 1 } ]
这不是最干净的方法,如果有人知道如何通过reduce
达到相同的结果,请告诉我。但是,它确实会产生相当容易处理的结果。
首先,您可以通过线性搜索来使用蛮力解决方案。
public int LinearSearchcount(int[] A, int data){
int count=0;
for(int i=0;i<A.length;i++) {
if(A[i]==data) count++;
}
return count;
}
但是,为了使用它,我们将时间复杂度设为 O(n(。但是通过使用二进制搜索,我们可以提高复杂性。
如果您尝试这样做,您可能会收到如下所示的错误。
array.reduce((acc, arr) => acc + (arr.label === 'foo'), 0); // Operator '+' cannot be applied to type 'boolean'.
一种解决方案是这样做
array = [
{ id: 1, label: 'foo' },
{ id: 2, label: 'bar' },
{ id: 3, label: 'foo' },
{ id: 4, label: 'bar' },
{ id: 5, label: 'foo' }
]
array.reduce((acc, arr) => acc + (arr.label === 'foo' ? 1 : 0), 0); // result: 3
- Javascript(Angular)从一个对象数组到第二个数组查找值
- Lodash 从值数组中查找数组中的值
- 使用JS查找数组的平均值
- 咖啡脚本数组查找下一个位置
- 角度:通过数组查找其索引返回对象的内容
- 在循环中缓存数组查找是否有任何性能提升
- 在关联数组查找中未定义
- javascript数组查找具有当前日期+日期的最近日期
- jQuery使用相同的数组查找和删除数组中的字符串
- javascript数组查找时间最长,ID第一,如果超过当前值
- Javascript数组查找最大值
- 在Moongoose (MongoDB)中通过嵌入引用数组查找文档
- 在mongodb中通过数组查找一个字段的文档
- 使JavaScript中的数组查找更高效
- Javascript数组查找对象或元组
- 高效的Javascript数组查找
- 如何在猫鼬中按对象数组查找
- If else数组查找
- 不能在嵌入式数组查找中使用计数变量
- 对象键vs数组查找性能