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


162

배열이 있습니다.

[1, 2, 3, 5, 2, 8, 9, 2]

얼마나 많은지 알고 싶습니다 2배열에 개가 .

for루프로 반복하지 않고 JavaScript에서 가장 우아한 방법은 무엇입니까 ?

답변:


90

매우 간단합니다 :

var count = 0;
for(var i = 0; i < array.length; ++i){
    if(array[i] == 2)
        count++;
}

53
아니, 내가 의미하는 것은 "for"로 반복하지 않는 것이다
— Leem

9
@Leem : 루핑이 나쁜 이유는 무엇입니까? 어떤 시점에서는 항상 반복됩니다. 분명히 루프를 숨기는 함수를 만들 것입니다. 이 "작업에 적합한 도구를 사용하고 싶지 않습니다"-요청 은 결코 의미가 없습니다. 그리고 우리는 가장 우아한 것이 무엇인지 논쟁 할 수 있습니다. 예를 들어, 요소별로 함수를 호출하여 값과 비교하는 것은 우아하지 않습니다.
— Felix Kling

2
웃음 : alert (eval ( '('+ my_array.join ( '== 2) + (') + '== 2)')) jsfiddle.net/gaby_de_wilde/gujbmych
— user40521

29
OP는 아마도 5 줄의 코드이며 변경 가능한 상태가 필요하기 때문에 루핑이 나쁘다고 생각합니다. 나중에 읽게 된 개발자는 시간을내어 그 기능을 확인하고 작업에서 집중력을 잃어야합니다. 추상화가 훨씬 뛰어납니다. const count = countItems(array, 2);구현 세부 사항은 내부에서 논쟁 할 수 있습니다.
— joeytwiddle

2
루프를 사용하지 말아야한다는 질문이 있기 때문에 정답이 아닙니다. 루프를 사용하지 않는 솔루션을 확인하십시오. stackoverflow.com/a/44743436/8211014
— Luis Orantes

289

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

친구에게 인사 : 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) 추가 메모리가 필요할 수 있습니다. 확실히 중간 배열을 생성 한 다음 해당 중간 배열의 요소를 계산하십시오.


1
이것은 좋은 FP 솔루션으로, 중간 배열을 생성하는 유일한 "문제"(대부분의 경우 관련이 없음)입니다.
— tokland

1
@tokland : 그것이 우려된다면, 할 수 있습니다array.reduce(function(total,x){return x==value? : total+1 : total}, 0)
— ninjagecko

1
@ninjagecko 삼항 연산자에 콜론이 하나만 있어야합니까? [...].reduce(function(total,x){return x==2 ? total+1 : total}, 0)
— A.Krueger

2
@tokland 필터가 중간 배열을 생성 하지 않을 수도 있습니다. 우수한 최적화 컴파일러는 배열의 길이 만 사용됨을 쉽게 인식 할 수 있습니다. 아마도 현재 JS 컴파일러 중 어느 것도 이것을 할만 큼 똑똑하지는 않지만 중요하지 않습니다. 파울러가 말한 것처럼 "무슨 일이 있다면 더 많은 일을하십시오". 열악한 코드를 작성하여 컴파일러 결함을 피하는 것은 근시안적입니다. 컴파일러가 짜증 나면 컴파일러를 수정하십시오. mlafeldt.github.io/blog/if-it-hurts-do-it-more-often
— John Henckel

나는 이것을 최적의 2017 솔루션이라고 생각합니다 const count = (list) => list.filter((x) => x == 2).length. 그런 다음 count(list)list는 숫자 배열을 호출 하여 사용하십시오 . const count = (list) => list.filter((x) => x.someProp === 'crazyValue').length객체 배열에서 crazyValue 인스턴스를 계산할 수도 있습니다. 이 속성은 속성과 정확히 일치합니다.
— agm1984

71

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가 암시 되는 곳 .


es6 for of 루프를 사용하는 것보다 필터 기능이 더 성능이 좋습니까?
— Niklas

1
@Niklas, (O (N) 모든 요소를 ​​확인해야하기 때문에) 동일하다고 생각하지만 브라우저 메모리와 캐시 메모리에 적합한 요소 및 컴퓨터 수에 따라 다릅니다. 답은 "복잡하다"입니다. :)
— Sverrisson

67

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);


8

lodash 또는 밑줄을 사용하는 경우 _.countBy 메소드는 배열의 각 값을 기준으로 집계 된 총계 오브젝트를 제공합니다. 하나의 값만 계산해야하는 경우이를 하나의 라이너로 전환 할 수 있습니다.

_.countBy(['foo', 'foo', 'bar'])['foo']; // 2

이것은 또한 숫자 배열에서도 잘 작동합니다. 귀하의 예에 대한 하나의 라이너는 다음과 같습니다.

_.countBy([1, 2, 3, 5, 2, 8, 9, 2])[2]; // 3

5
엄청난 과잉. 모든 고유 요소에 대한 카운터를 만듭니다. 낭비되는 보관 및 시간.
— metalim

5

내가 이것을 할 수있는 가장 이상한 방법은 다음과 같습니다.

(a.length-(' '+a.join(' ')+' ').split(' '+n+' ').join(' ').match(/ /g).length)+1

어디:

  • a 는 배열입니다
  • n 은 배열에서 계산할 숫자입니다.

내 제안은 while 또는 for 루프를 사용하십시오 ;-)


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
*/

2
정규 표현식을 줄일 수는 String(a).match(/2/g).length + 1있지만이 숫자 또는 구현이 두 자리 숫자로 잘 재생되지는 않습니다.
— Gary Green

2
[2, 22, 2]는 어떻습니까?
— Oduvan

2

필터와 같은 배열 함수를 사용하는 게시 된 솔루션의 대부분은 매개 변수화되지 않았기 때문에 불완전합니다.

카운트 할 요소를 런타임에 설정할 수있는 솔루션이 있습니다.

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보다 큰 요소의 수를 세도록 함수를 쉽게 변경할 수 있다는 것입니다.

reduce 함수를 인라인으로 선언 할 수도 있습니다.

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처럼 느껴집니다.
— masterxilo

2

정말, 왜 필요 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)
}

2

함수로 감싸는 것이 좋습니다.

let countNumber = (array,specificNumber) => {
    return array.filter(n => n == specificNumber).length
}

countNumber([1,2,3,4,5],3) // returns 1

2

다음은 O (N)의 모든 배열 항목 수를 얻는 ES2017 + 방법입니다.

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 ]
]

1

나는 당신이 찾고있는 것이 기능적 접근이라고 믿습니다.

    const arr = ['a', 'a', 'b', 'g', 'a', 'e'];
    const count = arr.filter(elem => elem === 'a').length;
    console.log(count); // Prints 3

elem === 'a'는 조건입니다. 자신의 것으로 바꾸십시오.


그것은 3 인쇄되지 않습니다,하지만 0이 문제를 해결하려면, 두 번째 행은 다음과 count = arr.filter(elem => elem === 'a').length나count = arr.filter(elem => {return elem === 'a'}).length
— WPomier

1

js array의 reduce 함수의 시작 팬입니다.

const myArray =[1, 2, 3, 5, 2, 8, 9, 2];
const count = myArray.reduce((count, num) => num === 2 ? count + 1 : count, 0)

실제로 멋진 모습을 원한다면 Array 프로토 타입에서 카운트 함수를 만들 수 있습니다. 그런 다음 재사용 할 수 있습니다.

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)

0

재귀에 의한 솔루션

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

1
이것은 빈 배열을 처리합니까?
— Andrew Grimm

@AndrewGrimm이 옳습니다. 자료의 경우는 arr.length == 0
— 저스틴 마이너

좋은 해결책! 나는 연습을 위해 재귀를 사용하여 무언가를 시도하고 있었고 당신의 모범은 내가하고있는 것보다 더 우아했습니다. 확실히 사용하는 것보다 더 복잡한 방법 filter, reduce또는 간단한 forLoop및 성능을 볼 때 또한, 더 비싼,하지만 여전히 재귀와 함께 일을하는 좋은 방법. 내 유일한 변화는 : 함수를 만들고 그 안에 필터를 추가하여 배열을 복사하고 원래 배열의 돌연변이를 피한 다음 재귀를 내부 함수로 사용하는 것이 더 낫다고 생각합니다.
— R. Marques

0

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);
}


0

코어 레벨 파일에서 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

0

다음은 자바 스크립트의 한 라이너입니다.

  1. 지도를 사용하십시오. (v === 2)배열에서 일치하는 값 을 찾아 1과 0으로 구성된 배열을 반환합니다.
  2. 감소를 사용하십시오. 찾은 총 수에 대해 배열의 모든 값을 추가하십시오.
[1, 2, 3, 5, 2, 8, 9, 2]
  .map(function(v) {
    return v === 2 ? 1 : 0;
  })
  .reduce((a, b) => a + b, 0);

결과는 3입니다.


0

실행 방법에 따라 :

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, …}

-7

JavaScript 배열에서 length 속성을 사용할 수 있습니다.

var myarray = [];
var count = myarray.length;//return 0

myarray = [1,2];
count = myarray.length;//return 2

먼저 필터링하면 길이를 사용할 수 있습니다. 즉 array.filter (x => x === 2) .length
— Scott Blanch
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.