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


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

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

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


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').lengthcount = 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.