배열이 있습니다.
[1, 2, 3, 5, 2, 8, 9, 2]
얼마나 많은지 알고 싶습니다 2
배열에 개가 .
for
루프로 반복하지 않고 JavaScript에서 가장 우아한 방법은 무엇입니까 ?
답변
매우 간단합니다 :
var count = 0;
for(var i = 0; i < array.length; ++i){
if(array[i] == 2)
count++;
}
답변
[ 이 답변은 약간 날짜가 있습니다 : 수정 사항 읽기 ]
친구에게 인사 : map
와 filter
와 reduce
와 forEach
와every
etc.
(블록 레벨 범위가 없기 때문에 자바 스크립트로 for 루프를 작성하는 경우가 많으므로 반복 인덱스 또는 값을 캡처하거나 복제 해야하는 경우 어쨌든 함수를 루프 본문으로 사용해야합니다. 일반적으로 더 효율적이지만 때로는 폐쇄가 필요합니다.)
가장 읽기 쉬운 방법 :
[....].filter(x => x==2).length
(우리는 쓸 수 있었다 .filter(function(x){return x==2}).length
대신 )
다음은 공간 효율적 (O (N) 대신 O (1))이지만 시간 측면에서 얼마나 많은 혜택 / 불이익을 지불하는지 잘 모르겠습니다 (방문한 이후로 일정한 요인이 아닌 것) 각 요소는 정확히 한 번) :
[....].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 컴파일러는 이러한 경우를 최적화하지 못하거나 사양으로 인해 불가능할 수도 있습니다. 따라서 간단한 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
, 자바 스크립트에서 ‘4’== 4와 같은 숫자 때문에 호출 .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
. 성능에 관심이 있다면 이것은 for-loop (O (N) 시간)와 동일한 성능이지만, O (N) 메모리 대신 O (N) 추가 메모리가 필요할 수 있습니다. 확실히 중간 배열을 생성 한 다음 해당 중간 배열의 요소를 계산하십시오.
답변
JS ES6 업데이트 :
===
올바른 비교를 얻으려면 항상 triple equals : 를 사용해야 합니다.
// 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
답변
내가 이것을 할 수있는 가장 이상한 방법은 다음과 같습니다.
(a.length-(' '+a.join(' ')+' ').split(' '+n+' ').join(' ').match(/ /g).length)+1
어디:
- a 는 배열입니다
- n 은 배열에서 계산할 숫자입니다.
내 제안은 while 또는 for 루프를 사용하십시오 😉
답변
일반적으로 루프를 사용하지 않는 것은 몇 가지 방법을 통해 과정을 전달하는 것을 의미 하지 루프를 사용합니다.
다음은 루프 증오 코더가 가격으로 그의 혐오를 충족시킬 수있는 방법입니다.
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
*/