배열이 있습니다.
[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
*/
