Ich habe ein Array mit sich wiederholenden Werten. Ich möchte die Anzahl der Vorkommen für einen bestimmten Wert ermitteln.
Wenn ich beispielsweise ein Array so definiert habe: var dataset = [2,2,4,2,6,4,7,8];
, möchte ich die Anzahl der Vorkommen eines bestimmten Werts im Array ermitteln. Das Programm sollte also zeigen, dass bei drei Vorkommen des Wertes 2
ein Vorkommen des Wertes 6
usw. auftritt.
Was ist der idiomatischste/eleganteste Weg, dies zu tun?
reduce
ist hier geeigneter als filter
, da sie kein temporäres Array nur zum Zählen aufbaut.
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);
Beachten Sie, dass es einfach ist, das zu erweitern, um ein benutzerdefiniertes übereinstimmendes Prädikat zu verwenden, beispielsweise um Objekte mit einer bestimmten Eigenschaft zu zählen:
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);
Das Zählen aller Elemente, dh das Erstellen eines Objekts wie {x:count of xs}
ist in Javascript kompliziert, da Objektschlüssel nur Zeichenfolgen sein können, sodass Sie ein Array mit gemischten Typen nicht zuverlässig zählen können. Die folgende einfache Lösung funktioniert jedoch in den meisten Fällen gut:
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);
In ES6 verwenden Sie das Objekt Map
, um Objekte beliebigen Typs zuverlässig zu zählen:
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);
Neuere Browser nur wegen der Verwendung von 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
array.filter(c => c === searchvalue).length;
Hier ist eine Möglichkeit,ALLEauf einmal anzuzeigen:
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
//}
Mit einer normalen Schleife können Sie die Vorkommen konsistent und zuverlässig finden:
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
DEMO:https://jsfiddle.net/a7q9k4uu/
Um es allgemeiner zu machen, könnte die Funktion eine Prädikatsfunktion mit benutzerdefinierter Logik akzeptieren (true
false
), die die endgültige Anzahl bestimmt. Zum Beispiel:
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
var dataset = [2,2,4,2,6,4,7,8], count = {}
dataset.forEach(function(el){
count[el] = count[el] + 1 || 1
});
console.log(count)
// {
// 2: 3,
// 4: 2,
// 6: 1,
// 7: 1,
// 8: 1
// }
Sie können die array.reduce(callback[, initialValue])
-Methode in JavaScript 1.8
verwenden.
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;
Sie können alle Elemente in einem Array in einer einzigen Zeile zählen, indem Sie verkleinern.
[].reduce((a,b) => (a[b] = a[b] + 1 || 1) && a, {})
Dies ergibt ein Objekt, dessen Schlüssel die verschiedenen Elemente im Array sind, und die Werte die Anzahl der Vorkommen von Elementen im Array. Sie können dann auf eine oder mehrere der Zählungen zugreifen, indem Sie auf einen entsprechenden Schlüssel des Objekts zugreifen.
Zum Beispiel, wenn Sie das Obige in eine Funktion namens count()
einschließen würden:
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
Ich fand es sinnvoller, eine Liste von Objekten mit einem Schlüssel für das, was gezählt wird, und einem Schlüssel für die Zählung zu erhalten:
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)
was gibt zurück:
[ { name: 2, count: 3 },
{ name: 4, count: 2 },
{ name: 6, count: 1 },
{ name: 7, count: 1 },
{ name: 8, count: 1 } ]
Es ist nicht die sauberste Methode, und wenn jemand weiß, wie man mit reduce
dasselbe Ergebnis erzielt, lass es mich wissen. Es führt jedoch zu einem Ergebnis, mit dem man relativ leicht arbeiten kann.
Erstens können Sie mit Brute Force Solution arbeiten, indem Sie mit der linearen Suche fortfahren.
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;
}
Um dies zu bewerkstelligen, erhalten wir die Zeitkomplexität als O (n). Aber durch die binäre Suche können wir unsere Komplexität verbessern.