Відповіді:
Дуже просто:
var count = 0;
for(var i = 0; i < array.length; ++i){
if(array[i] == 2)
count++;
}
const count = countItems(array, 2);і деталі реалізації можна аргументувати всередині.
[ ця відповідь трохи датована: прочитайте правки ]
Привітайтеся зі своїми друзями: mapі filterі reduceі forEachта і everyт.д.
(Я лише час від часу пишу for-loops у 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, ймовірно, не (або не можуть через специфіку) оптимізувати подібні випадки. Тож вам справді слід написати простий цикл:
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підкреслює, що він використовує== оператор.)
Також розглядайте можливість використовувати власну структуру даних із безлічі (наприклад, як ' collections.Counter' python ' '), щоб уникнути необхідності підрахунку в першу чергу.
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. Якщо ви дбаєте про продуктивність, зауважте, що, хоча це асимптотично та ж продуктивність, що і час для циклу (O (N)), можливо, це потребуватиме O (N) додаткової пам'яті (замість O (1) пам'яті), оскільки це буде майже безумовно, генерують проміжний масив, а потім підраховують елементи цього проміжного масиву.
array.reduce(function(total,x){return x==value? : total+1 : total}, 0)
[...].reduce(function(total,x){return x==2 ? total+1 : total}, 0)
const count = (list) => list.filter((x) => x == 2).length. Потім використовуйте його, називаючи, count(list)де список є масивом чисел. Ви також const count = (list) => list.filter((x) => x.someProp === 'crazyValue').lengthможете порахувати випадки crazyValue в масиві об’єктів. Зауважте, це точна відповідність для власності.
Оновлення 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мається на увазі.
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
Не використовувати цикл зазвичай означає передачу процесу якомусь методу, який використовує цикл.
Ось спосіб, котрий наш штриховий кодер може задовольнити його ненависть, ціною:
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
*/
String(a).match(/2/g).length + 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);
var elementToFind=2; ... function (elementToFind, total, number){ return total += number==elementToFind; }.bind(this, elementToFind) ...важче читати і не дає переваги перед просто ... (acc, x) => acc += number == 2.... Мені подобається, що ти використовуєш +=замість цього acc + (number == 2). Відчуває себе як необгрунтований синтаксис HACK, хоча.
Дійсно, навіщо вам це потрібно 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)
}
Краще ввімкнути його у функцію:
let countNumber = (array,specificNumber) => {
return array.filter(n => n == specificNumber).length
}
countNumber([1,2,3,4,5],3) // returns 1
Ось 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 ]
]
Я вважаю, що ви шукаєте - це функціональний підхід
const arr = ['a', 'a', 'b', 'g', 'a', 'e'];
const count = arr.filter(elem => elem === 'a').length;
console.log(count); // Prints 3
elem === 'a' - це умова, замініть її своєю.
count = arr.filter(elem => elem === 'a').lengthабоcount = arr.filter(elem => {return elem === 'a'}).length
Я починаючий фанат функції зменшення масиву js.
const myArray =[1, 2, 3, 5, 2, 8, 9, 2];
const count = myArray.reduce((count, num) => num === 2 ? count + 1 : count, 0)
Насправді, якщо ви дійсно хочете пофантазувати, ви можете створити функцію підрахунку на прототипі масиву. Потім ви можете його повторно використовувати.
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)
Розчин за допомогою рекурсії
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
filter, reduceабо простий forLoop, а також більш дорогий при перегляді продуктивності, але все-таки чудовий спосіб зробити це з рекурсією. Моя єдина зміна: я просто думаю, що було б краще створити функцію і додати в неї фільтр, щоб скопіювати масив і уникнути мутації вихідного масиву, а потім використовувати рекурсивну як внутрішню функцію.
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.
(v === 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, …}
Ви можете використовувати властивість length у масиві JavaScript:
var myarray = [];
var count = myarray.length;//return 0
myarray = [1,2];
count = myarray.length;//return 2