[javascript] 배열에서 특정 요소를 계산하는 방법은 무엇입니까?

배열이 있습니다.

[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++;
}


답변

[ 이 답변은 약간 날짜가 있습니다 : 수정 사항 읽기 ]

친구에게 인사 : mapfilterreduceforEachevery 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
*/