배열에 JavaScript의 값이 포함되어 있는지 어떻게 확인합니까?


3995

JavaScript 배열에 값이 포함되어 있는지 확인하는 가장 간결하고 효율적인 방법은 무엇입니까?

이것이 내가 아는 유일한 방법입니다.

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
}

이것을 달성하는 더 좋고 간결한 방법이 있습니까?

이것은 스택 오버플로 질문과 매우 밀접한 관련이 있습니다 . JavaScript 배열에서 항목을 찾는 가장 좋은 방법은 무엇입니까? 를 사용하여 배열에서 객체 찾기를 처리합니다 indexOf.


49
방금 테스트 : indexOf를 사용하는 동안 jsperf.com/find-element-in-obj-vs-array/2 (변수에 a.length를 미리 저장하는 것 제외) : .inArray) 속도가 훨씬 느림
— Jörn Berkefeld

17
많은 사람들이 여기서 Array # indexOf가 최선의 선택이라고 대답했습니다. 그러나 부울로 올바르게 캐스트 할 수있는 것을 원하면 이것을 사용하십시오 : ~[1,2,3].indexOf(4)0을 반환하면 false로 평가되고 ~[1,2,3].indexOf(3)-3을 반환하면 true로 평가됩니다.
— lordvlad

8
~부울로 변환하는 데 사용하려는 것이 아닙니다 !. 그러나이 경우 -1과의 동등성을 확인하려면 함수가 return [1,2,3].indexOf(3) === -1; ~이진이 아닌 종료 될 수 있으므로 값의 각 비트를 개별적으로 반전시킵니다.
— mcfedr 2016 년

14
@Iordvlad [1,2,3].indexOf(4)는 실제로 -1을 반환 합니다. @mcfedr 지적으로 ~는 IS 비트 단위 NOT 연산자 , ES5 11.4.8 참조하십시오. 이진 표현은 -11로만 구성되므로 보수는입니다 0. 이는 거짓으로 평가됩니다. 다른 숫자의 보수는 0이 아니므로 참입니다. 따라서 ~잘 작동하며 종종와 함께 사용됩니다 indexOf.
— mknecht

5
제목이 잘못되었습니다. 어디 [[1,2],[3,4]].includes([3,4])입니까?
— mplungjan

답변:


4374

현대 브라우저가 Array#includes않는, 정확히 있고 광범위하게 지원되는 IE를 제외한 모든 사람이 :

console.log(['joe', 'jane', 'mary'].includes('jane')); //true

Array#indexOf직접적이지는 않지만 오래된 브라우저의 경우 폴리 필이 필요하지 않은을 사용할 수도 있습니다 .


많은 프레임 워크에서도 비슷한 방법을 제공합니다.

일부 프레임 워크에서는이를 함수로 구현하고 다른 프레임 워크는 함수를 배열 프로토 타입에 추가합니다.


42
MooTools에는 또한 부울을 반환하는 Array.contains가 있으며 여기에서 실제 질문처럼 들립니다.
— Ryan Florence

22
또한 프로토 타입은 Array.include부울을 반환합니다
— user102008

46
좋은 브라우저를 사용하는 경우 다음을 사용할 수 있습니다.array.indexOf(object) != -1
— Sam Soffes

13
또한, 그나마 사용 같이 IndexOf, 조건으로 단독 첫 번째 요소는 0 반환하고 falsy로 평가되기 때문에
— 플러스 -

241
inArray요소의 인덱스를 반환하고 -1존재하지 않는 경우 함수의 끔찍한 이름입니다 . 부울이 반환 될 것으로 기대합니다.
— Tim

434

2019 년 업데이트 :이 답변은 2008 년 (11 세)부터이며 최신 JS 사용과 관련이 없습니다. 약속 된 성능 향상은 당시의 브라우저에서 수행 된 벤치 마크를 기반으로했습니다. 최신 JS 실행 컨텍스트와 관련이 없을 수 있습니다. 쉬운 해결책이 필요하면 다른 답변을 찾으십시오. 최상의 성능이 필요한 경우 관련 실행 환경에서 벤치마킹하십시오.

다른 사람들이 말했듯이 배열을 반복하는 것이 가장 좋은 방법 일 수 있지만 JavaScript에서 루프를 줄이는 것이 가장 빠른 방법 이라는 것이 입증되었습니다while . 따라서 다음과 같이 코드를 다시 작성하십시오.

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

물론 Array 프로토 타입을 확장 할 수도 있습니다.

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

이제 다음을 간단히 사용할 수 있습니다.

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false


22
"증명 된"은 강력한 단어입니다. JS 엔진은 지속적으로 개선되고 3 년 전에 측정 된 실행 시간은 굉장히 오래되었습니다.
— orip

2
@Damir-동의합니다. 가능하면 indexOf를 사용하도록 샘플을 변경하십시오.이 코드를 맹목적으로 복사하여 붙여 넣는 사람들은 최상의 성능을 얻을 수 있습니다.
— orip

1
@cbmeeks 예, 관리가 반드시 필요합니다. 그것은 for (o in array)일반적으로 배열을 반복 할 때 수행해서는 안되는 경우 일 것입니다 ...
— Damir Zekić

1
[1, 2, 3] .indexOf (1)> -1 경우 이렇게하는 가장 좋은 방법은 체크 인
— 데빈 G로드

207

indexOf 어쩌면 "ECMA-262 표준에 대한 자바 스크립트 확장입니다. 표준의 다른 구현에는 없을 수 있습니다."

예:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1

AFAICS 마이크로 소프트는 않습니다 하지 대체 어떤 종류의 제공 이에,하지만 당신은 Internet Explorer의 배열 (지원을하지 않는 다른 브라우저에 유사한 기능을 추가 할 수 있습니다 indexOf당신이 원하는 경우)에, A와 빠른 Google 검색은 계시 (예를 들어, 이 일을 ).


실제로 링크 한 developer.mozilla.org 페이지에서이를 지원하지 않는 브라우저의 indexOf 확장 구현 예제가 있습니다.
— Lloyd Cotten

실제로, 인덱스를 지원하지 않는 브라우저 (예 : IE7) 용 Array의 프로토 타입에 indexof를 추가하면 배열의 항목을 반복 할 때이 함수를 반복하려고 시도합니다. 추잡한.
— CpILL


Object를 확인할 수 있습니까? 나는 그것이 객체의 경우에는 효과가 없다고 생각합니다
— Himesh Aadeshara

169

ECMAScript 7에서 소개 Array.prototype.includes합니다.

다음과 같이 사용할 수 있습니다 :

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

선택적 두 번째 인수도 허용합니다 fromIndex.

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

달리 indexOf사용하는, 엄격한 평등 비교 , includes사용 비교 SameValueZero의 평등 알고리즘을. 즉, 배열에 다음이 포함되어 있는지 감지 할 수 있습니다 NaN.

[1, 2, NaN].includes(NaN); // true

또한 달리 indexOf, includes인덱스 누락 건너 뛰지 않습니다 :

new Array(5).includes(undefined); // true

현재 초안이지만 모든 브라우저에서 작동 하도록 폴리 필 할 수 있습니다 .


3
IE와 Microsfot 에지 (2015) (지원되지 않음 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... )
— 아드리아누 센드

1
또한 관련이있는 ES7 호환성 표 (크롬에서 지원하는 것처럼
— 보임

Object를 확인할 수 있습니까? 나는 그것이 개체의 경우에는 효과가 있다고 생각하지 않습니다
— Himesh Aadeshara

128

상단 답변은 기본 유형을 가정하지만 배열에 특성 이있는 객체 가 있는지 확인하려면 Array.prototype.some () 은 매우 우아한 솔루션입니다.

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

그것에 대한 좋은 점은 요소가 발견되면 반복이 중단되어 불필요한 반복 사이클이 절약된다는 것입니다.

또한 if부울을 반환하므로 명령문 에 잘 맞습니다 .

if (items.some(item => item.a === '3')) {
  // do something
}

* 의견에서 제임스가 지적한 바와 같이, 2018 년 9 월이 답변 시점에서 caniuse.com 지원 표Array.prototype.some() 가 완전히 지원됩니다.


1
오늘, 2018 년 9 월 현재, Array.prototype.some ()이 완전히 지원됩니다 : caniuse.com 지원 테이블
— jamess

1
AWS Node.js Lambda의 노드> = 8.10에서 작업하므로이 방법이 좋습니다. 매우 깨끗하고 간단한 해결책! 👍🏻
— Jordan

1
@jamess 잘 지원 될 수 있지만 Arrow functions이 예제에서는 지원이 잘되지 않음을 기억하십시오 . 자세한 내용은 여기를 참조하십시오 : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
— Kamil Witkowski

단락이 있습니까? 아니면 값을 찾더라도 전체 배열을 반복합니까?
— Douglas Gaskell

@DouglasGaskell 그것은 일단 발견 된 반복을 중단합니다 (답변에 언급 됨)
— Michael

112

다음과 같이 배열을 정의했다고 가정 해 봅시다.

const array = [1, 2, 3, 4]

아래에 세 가지가 있는지 확인하는 방법 3이 있습니다. 모두 true또는을 반환합니다 false.

기본 배열 방법 (ES2016부터) ( 호환성 표 )

array.includes(3) // true

사용자 정의 배열 방법으로 (ES2016 이전)

// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true

간단한 기능

const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true

"b"가 배열 "a"에 있으면 true를 반환합니다. 다른 방법을 모르겠습니다 ...
— william malo

4
이 부분은 "!! ~"를 이해하지 못합니다. IE8은 Array 객체에서 indexOf ()를 지원하지 않기 때문에 IE8에서는 작동하지 않을 것이라고 생각합니다.
— svlada 2016 년

62
"~"는 숫자에서 1을 바닥, 반전 및 빼는 연산자입니다. indexOf가 실패하면 -1을 반환하므로 "~"는 -1을 "0"으로 바꿉니다. "!!"사용 boleans에 회전 수 (! 0 === 거짓)
— 윌리엄 말로

1
"> -1".length === "!! ~".length
— super

2
부울 연산자의 비전문가 효과에 대한 지식이 부족하다고 생각합니다. 그러나 나는 읽을 수있는 코드의 가치에 동의합니다. 확실히 레이블이 지정된 함수로 이것을 감쌀 것입니다. 이것이 바로 대부분의 주요 JS 프레임 워크가하는 일입니다.
— okdewit

79

여기의 자바 스크립트 1.6 호환 의 구현 Array.indexOf:

if (!Array.indexOf) {
    Array.indexOf = [].indexOf ?
        function(arr, obj, from) {
            return arr.indexOf(obj, from);
        } :
        function(arr, obj, from) { // (for IE6)
            var l = arr.length,
                i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
            i = i < 0 ? 0 : i;
            for (; i < l; i++) {
                if (i in arr && arr[i] === obj) {
                    return i;
                }
            }
            return -1;
        };
}

이것은 멋지지만 약간 혼란스러워 보입니다. * 1 줄과 3 줄에 대한 테스트가 아닙니까? 프로토 타입을 테스트하고 필요한 경우 Array.prototype에 함수를 추가하는 것이 더 좋지 않습니까?
— Avi Flax

10
그들은 동등하지 않습니다. [].indexOf의 속기입니다 Array.prototype.indexOf. 편집증 방어적인 자바 스크립트 프로그래머는 모든 비용으로 기본 프로토 타입을 확장하지 않아도됩니다.
— Már Örlygsson

1
되지 않은 [].indexOf새로운 배열을 생성하고 액세스하는 indexOf동안, Array.prototype.indexOf단지 바로 프로토 타입을 액세스?
— alex

3
@alex yes [].indexOf === Array.prototype.indexOf(FireBug에서 사용해보십시오), 반대로 [].indexOf !== Array.indexOf.
— Már Örlygsson

57

사용하다:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}

25
x ? true : false일반적으로 중복됩니다. 여기 있어요
— Ry-

@minitech 왜 중복이라고 말합니까?
— Matías Cánepa

8
array.indexOf(search) >= 0이미 부울입니다. 그냥 return array.indexOf(search) >= 0.
— Ry-

@minitech 잘 감사합니다! 실제로 나는 그러한 건축이 반환 될 수 있다는 것을 몰랐습니다. 새로운 것까지.
— Matías Cánepa

말 그대로 자바 스크립트의 모든 구문을 반환 할 수 있습니다
— BT

49

JavaScript Array객체를 확장 하는 것은 for-in기존 스크립트를 손상시킬 수있는 새로운 속성 (사용자 정의 메소드)을 루프에 도입하기 때문에 정말 나쁜 생각 입니다. 몇 년 전 프로토 타입 라이브러리 의 저자는 이런 종류의 것을 제거하기 위해 라이브러리 구현을 리엔지니어링해야했습니다.

페이지에서 실행되는 다른 JavaScript와의 호환성에 대해 걱정할 필요가 없다면 계속하십시오. 그렇지 않으면 더 어색하지만 더 안전한 독립형 기능 솔루션을 사용하는 것이 좋습니다.


22
동의하지 않습니다. 정확하게 For-in 루프를 배열에 사용해서는 안됩니다. 유명한 js 라이브러리 중 하나를 사용할 때 for-in 루프를 사용하면 중단됩니다
— Tomas

이것이 원숭이 패치로 간주됩니까? lol 그런 사람들이 있습니다.
— cbmeeks

33

짧막 한 농담:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}

8
array.filter(e=>e==x).length > 0에 해당 array.some(e=>e==x)하지만, some더 효율적입니다
— 아폴로


28

나는 다음을 사용한다 :

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false


19

희망적으로 더 빠른 양방향 indexOf/ lastIndexOf대안

2015 년

새로운 메소드 include 는 매우 훌륭하지만, 현재는 기본적으로 지원이 없습니다.

느린 indexOf / lastIndexOf 함수를 대체하는 방법을 생각한 지 오래되었습니다.

가장 좋은 답변을 보면서 수행 가능한 방법이 이미 발견되었습니다. 그 contains중에서 @Damir Zekic이 게시 한 기능 중 가장 빠른 기능을 선택했습니다 . 그러나 벤치 마크는 2008 년부터 시작되었으며 구식이기도합니다.

나는 또한 whileover 선호 for하지만 특별한 이유는 없기 때문에 for 루프로 함수 작성을 종료했습니다. 또한로 수행 할 수 있습니다 while --.

배열을 수행하는 동안 배열의 양쪽을 확인하면 반복이 훨씬 느리면 궁금했습니다. 분명히 아니요. 따라서이 기능은 가장 많이 뽑힌 투표보다 2 배 정도 빠릅니다. 분명히 그것은 또한 네이티브보다 빠릅니다. 실제 환경에서 검색하는 값이 배열의 시작 또는 끝에 있는지 알 수없는 환경입니다.

방금 값을 가진 배열을 푸시했다는 것을 알면 lastIndexOf를 사용하는 것이 가장 좋은 해결책 일 수 있지만 큰 배열을 통과해야하고 결과가 어디에나있을 수있는 경우 상황을 더 빠르게 만드는 견고한 솔루션 일 수 있습니다.

양방향 indexOf / lastIndexOf

function bidirectionalIndexOf(a, b, c, d, e){
  for(c=a.length,d=c*1; c--; ){
    if(a[c]==b) return c; //or this[c]===b
    if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
  }
  return -1
}

//Usage
bidirectionalIndexOf(array,'value');

성능 테스트

http://jsperf.com/bidirectionalindexof

테스트로 100k 항목으로 배열을 만들었습니다.

세 가지 쿼리 : 배열의 시작, 중간 및 끝.

이 내용이 흥미롭고 성능을 테스트하기를 바랍니다.

참고 : 나는 약간 수정 된 알 수 있듯이 contains(그래서 기본적으로 같이 IndexOf 및 lastIndexOf에서도 출력을 반영하기 위해 기능을 true로 index와 false함께 -1). 그것은 해를 끼치 지 않아야합니다.

배열 프로토 타입 변형

Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
  for(c=this.length,d=c*1; c--; ){
    if(this[c]==b) return c; //or this[c]===b
    if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
  }
  return -1
},writable:false, enumerable:false});

// Usage
array.bidirectionalIndexOf('value');

이 함수는 true 또는 false 또는 객체, 문자열 또는 그 밖의 것을 반환하도록 쉽게 수정할 수 있습니다.

그리고 여기 while변형이 있습니다 :

function bidirectionalIndexOf(a, b, c, d){
  c=a.length; d=c-1;
  while(c--){
    if(b===a[c]) return c;
    if(b===a[d-c]) return d-c;
  }
  return c
}

// Usage
bidirectionalIndexOf(array,'value');

이것이 어떻게 가능한지?

배열에서 반사 인덱스를 얻는 간단한 계산은 너무 간단하여 실제 루프 반복을 수행하는 것보다 두 배 빠릅니다.

반복 당 세 번의 검사를 수행하는 복잡한 예는 다음과 같지만 계산 시간이 길어 코드가 느려지는 경우에만 가능합니다.

http://jsperf.com/bidirectionalindexof/2


18

공연

오늘 2020.01.07 저는 Chrome v78.0.0의 MacOs HighSierra 10.13.6, Safari v13.0.4 및 Firefox v71.0.0에서 15 개의 선택된 솔루션에 대한 테스트를 수행합니다. 결론

  • 솔루션을 기반으로 JSON, Set놀랍게도 find(K, N, O)는 모든 브라우저에서 느린이다
  • es6 includes(F)는 크롬에서만 빠릅니다.
  • for(C, D) 및 indexOf(G, H) 기반 솔루션 은 크고 작은 어레이의 모든 브라우저에서 매우 빠르므로 효율적인 솔루션을위한 최상의 선택 일 수 있습니다.
  • 루프 동안 인덱스가 감소하는 솔루션, (B) CPU 캐시 작동 방식 때문에 속도가 느려질 수 있습니다 .
  • 또한 검색 된 요소가 배열 길이의 66 % 위치에있을 때 큰 배열에 대한 테스트를 실행하고 for(C, D, E) 기반 솔루션 은 비슷한 결과를 제공합니다 (~ 630 ops / sec-safari 및 firefox의 E는 10- C 및 D보다 20 % 느림)

결과

여기에 이미지 설명을 입력하십시오

세부

10 가지 요소가있는 배열과 1 개의 요소가있는 배열의 경우 2 가지 테스트 사례를 수행합니다. 두 경우 모두 검색된 요소를 배열 중간에 넣습니다.

작은 배열-10 개 요소

당신은 당신의 컴퓨터에서 테스트를 수행 할 수 HERE

여기에 이미지 설명을 입력하십시오

큰 배열-1.000.000 요소

당신은 당신의 컴퓨터에서 테스트를 수행 할 수 HERE

여기에 이미지 설명을 입력하십시오


16

JavaScript 1.6 이상 (Firefox 1.5 이상)을 사용하는 경우 Array.indexOf 를 사용할 수 있습니다 . 그렇지 않으면 원래 코드와 비슷한 것으로 끝날 것이라고 생각합니다.


16
function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

배열 인덱스가있는 경우, 또는 -1이없는 경우 -1을 반환합니다


16

이 스 니펫을 사용합니다 (객체, 배열, 문자열과 함께 작동).

/*
 * @function
 * @name Object.prototype.inArray
 * @description Extend Object prototype within inArray function
 *
 * @param {mix}    needle       - Search-able needle
 * @param {bool}   searchInKey  - Search needle in keys?
 *
 */
Object.defineProperty(Object.prototype, 'inArray',{
    value: function(needle, searchInKey){

        var object = this;

        if( Object.prototype.toString.call(needle) === '[object Object]' || 
            Object.prototype.toString.call(needle) === '[object Array]'){
            needle = JSON.stringify(needle);
        }

        return Object.keys(object).some(function(key){

            var value = object[key];

            if( Object.prototype.toString.call(value) === '[object Object]' || 
                Object.prototype.toString.call(value) === '[object Array]'){
                value = JSON.stringify(value);
            }

            if(searchInKey){
                if(value === needle || key === needle){
                return true;
                }
            }else{
                if(value === needle){
                    return true;
                }
            }
        });
    },
    writable: true,
    configurable: true,
    enumerable: false
});

용법:

var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first");          //true
a.inArray("foo");            //false
a.inArray("foo", true);      //true - search by keys
a.inArray({three: "third"}); //true

var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one");         //true
b.inArray('foo');         //false
b.inArray({foo: 'val'})   //true
b.inArray("{foo: 'val'}") //false

var c = "String";
c.inArray("S");        //true
c.inArray("s");        //false
c.inArray("2", true);  //true
c.inArray("20", true); //false

15

배열에 객체가 있는지 반복적으로 확인하는 경우 조사해야 할 수도 있습니다.

  1. 삽입 정렬 을 수행하여 배열을 항상 정렬 유지 (새 개체를 올바른 위치에 배치)
  2. 개체를 제거 + 정렬 된 삽입 작업으로 업데이트하고
  3. 에서 이진 검색 조회를 사용하십시오 contains(a, obj).

2
또는 가능하면 MattMcKnight 및 ninjagecko가 제안한 것처럼 Array 사용을 완전히 중지하고 Object를 사전으로 사용하십시오.
— joeytwiddle

13

모든 최신 브라우저에서 작동하는 솔루션 :

function contains(arr, obj) {
  const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
  return arr.some(item => JSON.stringify(item) === stringifiedObj);
}

용법:

contains([{a: 1}, {a: 2}], {a: 1}); // true

IE6 + 솔루션 :

function contains(arr, obj) {
  var stringifiedObj = JSON.stringify(obj)
  return arr.some(function (item) {
    return JSON.stringify(item) === stringifiedObj;
  });
}

// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
  Array.prototype.some = function (tester, that /*opt*/) {
    for (var i = 0, n = this.length; i < n; i++) {
      if (i in this && tester.call(that, this[i], i, this)) return true;
    } return false;
  };
}

용법:

contains([{a: 1}, {a: 2}], {a: 1}); // true

왜 사용 JSON.stringify합니까?

Array.indexOf및 Array.includes(뿐만 아니라 답변 여기에 대부분의 등)만을 기준으로 비교하지 값을 기준으로.

[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object

보너스

최적화되지 않은 ES6 원 라이너 :

[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true

참고 : 키의 순서가 동일한 경우 값을 기준으로 개체를 비교하는 것이 더 좋으므로 다음과 같은 패키지를 사용하여 키를 먼저 정렬 할 수 있습니다. https://www.npmjs.com/package/sort-keys


contains성능 최적화로 기능을 업데이트했습니다 . 덕분에 itinance 을 지적.


이 특정 코드 덩어리는 IE6에서 작동 할 수 있지만 (테스트되지 않음) IE는 IE9까지 ES5를 지원하지 않았습니다.
— Mark Reed

성능상의 이유로 엄격하지 않아야합니다. 적어도 루프마다 "obj"를 JSON.stringify하지 않아야한다. 비용이 많이 들고 애플리케이션 속도가 느리기 때문이다. 당신은 전에 캡처해야 그 때문에 임시 변수에-루프
— itinance

1
@itinance 좋은 지적. includes귀하의 제안으로 기능을 업데이트했습니다 . 내 기능으로 jsperf를 실행했습니다. lodash에 포함 된 것보다 약 5 배 느립니다. lodash는 값을 기준으로 비교하지 않으며 {a: 1}에서 찾을 수 없습니다 [{a: 1}]. 라이브러리가 있는지 모르겠습니다. 그러나 더 수행적이고 미친 듯이 복잡한 방법이 없는지 궁금합니다.
— Igor Barbashin

늦은 참고 : contains([{ a: 1, b: 2 }], { b: 2, a: 1 })문자열로 된 객체가 속성의 순서를 유지하기 때문에 이것은 작동하지 않습니다 .
— Heretic Monkey

1
@HereticMonkey, 사실입니다. 그래서 sort-keys하단에 메모를 추가 한 것입니다.
— Igor Barbashin

12

lodash의 일부를 사용하십시오 기능을 .

간결하고 정확하며 뛰어난 크로스 플랫폼 지원을 제공합니다.

허용 된 답변은 요구 사항을 충족하지도 않습니다.

요구 사항 : JavaScript 배열에 객체가 포함되어 있는지 확인하는 가장 간결하고 효율적인 방법을 권장합니다.

허용 된 답변 :

$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1

내 추천 :

_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true

노트:

$ .inArray는 스칼라 배열에 스칼라 값이 있는지 여부를 결정하는 데 효과적 입니다 ...

$.inArray(2, [1,2])
> 1

...하지만 질문은 분명히 물체의 여부를 결정하는 효율적인 방법을 요구 합니다 가 배열에 포함되어 .

스칼라와 객체를 모두 처리하기 위해 다음을 수행 할 수 있습니다.

(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)

10

ECMAScript 6에는 찾기에 대한 훌륭한 제안이 있습니다.

find 메소드는 콜백이 참 값을 리턴하는 요소를 찾을 때까지 배열에있는 각 요소에 대해 콜백 함수를 한 번 실행합니다. 이러한 요소를 찾으면 find는 해당 요소의 값을 즉시 리턴합니다. 그렇지 않으면 find는 정의되지 않은 리턴을 리턴합니다. 콜백은 값이 할당 된 배열의 인덱스에 대해서만 호출됩니다. 삭제되었거나 값이 할당되지 않은 인덱스에 대해서는 호출되지 않습니다.

여기에 MDN 문서 가 있습니다.

찾기 기능은 다음과 같이 작동합니다.

function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5

함수 를 정의하여 ECMAScript 5 이하에서이를 사용할 수 있습니다 .

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(predicate) {
      if (this == null) {
        throw new TypeError('Array.prototype.find called on null or undefined');
      }
      if (typeof predicate !== 'function') {
        throw new TypeError('predicate must be a function');
      }
      var list = Object(this);
      var length = list.length >>> 0;
      var thisArg = arguments[1];
      var value;

      for (var i = 0; i < length; i++) {
        if (i in list) {
          value = list[i];
          if (predicate.call(thisArg, value, i, list)) {
            return value;
          }
        }
      }
      return undefined;
    }
  });
}


9

array.indexOf(x)!=-1이 작업을 수행하는 가장 간결한 방법 이지만 (Internet Explorer 이외의 브라우저에서 10 년 이상 지원하고 있지만) O (1)이 아니라 O (N)입니다. 배열이 변경되지 않으면 배열을 해시 테이블로 변환 한 다음 table[x]!==undefined또는 ===undefined:

Array.prototype.toTable = function() {
    var t = {};
    this.forEach(function(x){t[x]=true});
    return t;
}

데모:

var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})

(안타깝게도 Array.prototype.contains를 만들어 배열을 "고정"하고 해시 테이블을 this._cache에 두 줄로 저장할 수 있지만 나중에 배열을 편집하도록 선택하면 잘못된 결과가 나타납니다. 예를 들어 파이썬과 달리이 상태를 유지하십시오.)


9

"has ()"메소드가있는 Set 을 사용할 수 있습니다 .

function contains(arr, obj) {
      var proxy = new Set(arr);
      if (proxy.has(obj))
        return true;
      else
        return false;
    }

    var arr = ['Happy', 'New', 'Year'];
    console.log(contains(arr, 'Happy'));


5
나는 return proxy.has(obj)if-else 문장으로 두 줄보다 훨씬 더 깨끗 하다고 생각 합니다.
— Maciej Bukowski

function contains(arr, obj) { return new Set(arr).has(obj); }
— 고든 빈

8

사용하다:

var myArray = ['yellow', 'orange', 'red'] ;

alert(!!~myArray.indexOf('red')); //true

데모

tilde ~이 시점에서 정확히 무엇을하는지 알기 위해서는 이 질문을 참조하십시오 . .


5
이것은 이미 1 년 반 전에 게시되었지만 반복 할 필요는 없습니다.
— Shadow Wizard is Ear For You

3
실제로 게시되지 않았습니다. 답변이 아니라 답변에 대한 주석으로, 심지어 명확하고 간결하지 않습니다. 게시 해 주셔서 감사합니다. Mina Gabriel.
— T.CK

6

좋아, 당신은 결과를 얻기 위해 코드를 최적화 할 수 있습니다!

더 깨끗하고 더 나은 방법은 여러 가지가 있지만 패턴을 가져 와서 적용하고 싶었습니다. JSON.stringify단순히 다음과 같이하십시오.

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
            return true;
        }
    }
    return false;
}

늦은 참고 : contains([{ a: 1, b: 2 }], { b: 2, a: 1 })문자열로 된 객체가 속성의 순서를 유지하기 때문에 이것은 작동하지 않습니다 .
— Heretic Monkey

5

결코 최고는 아니지만, 나는 단지 창의력을 발휘하고 레퍼토리에 추가하고있었습니다.

이것을 사용하지 마십시오

Object.defineProperty(Array.prototype, 'exists', {
  value: function(element, index) {

    var index = index || 0

    return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
  }
})


// Outputs 1
console.log(['one', 'two'].exists('two'));

// Outputs -1
console.log(['one', 'two'].exists('three'));

console.log(['one', 'two', 'three', 'four'].exists('four'));


그렇지 않으면 무엇을 사용해야합니까?
— bryc

@bryc는 아마도 받아 들여진 해결책이거나 다른 해결책 일 것입니다. 성능에 신경 쓰지 않는다면 이것을 사용할 수있는 것보다
— sqram

5

이 질문에 여전히 최신 구문이 추가되지 않아서 2 센트를 추가 한 것에 놀랐습니다.

객체 arrObj의 배열이 있고 그 안에서 obj를 찾고 싶다고 가정 해 봅시다.

Array.prototype. indexOf- > ( index 또는 -1 반환 )는 일반적으로 배열에서 요소의 색인을 찾는 데 사용됩니다. 객체 검색에도 사용할 수 있지만 동일한 객체에 대한 참조를 전달하는 경우에만 작동합니다.

let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];


console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1

console.log([1, 3, 5, 2].indexOf(2)); //3

Array.prototype. 포함 -> ( true 또는 false 반환 )

console.log(arrObj.includes(obj));  //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false

console.log([1, 3, 5, 2].includes(2)); //true

Array.prototype. find- > (콜백을 수행 하고 CB에서 true를 리턴하는 첫 번째 값 / 객체 를 리턴 함)

console.log(arrObj.find(e => e.age > 40));  //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }

console.log([1, 3, 5, 2].find(e => e > 2)); //3

Array.prototype. findIndex- > (콜백을 수행 하고 CB에서 true를 리턴하는 첫 번째 값 / 객체의 색인 을 리턴 함)

console.log(arrObj.findIndex(e => e.age > 40));  //1
console.log(arrObj.findIndex(e => e.age > 40)); //1

console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1

find와 findIndex는 콜백을 취하기 때문에 참 조건을 창의적으로 설정하여 배열에서 객체를 가져올 수 있습니다 (참조가없는 경우에도).


5

이 요구 사항에 대한 간단한 솔루션은 find()

아래와 같은 객체 배열이 있다면

var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];

그런 다음 값이있는 객체가 이미 있는지 여부를 확인할 수 있습니다

let data = users.find(object => object['id'] === '104');

data가 null이면 admin이 없으면 아래처럼 기존 객체를 반환합니다.

{id: "104", name: "admin"}

그런 다음 배열에서 해당 객체의 색인을 찾아 아래 코드를 사용하여 객체를 교체 할 수 있습니다.

let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.log(users);

당신은 아래와 같은 가치를 얻을 것입니다

[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];

이것이 누군가를 도울 수 있기를 바랍니다.


5

    function countArray(originalArray) {
     
    	var compressed = [];
    	// make a copy of the input array
    	var copyArray = originalArray.slice(0);
     
    	// first loop goes over every element
    	for (var i = 0; i < originalArray.length; i++) {
     
    		var count = 0;	
    		// loop over every element in the copy and see if it's the same
    		for (var w = 0; w < copyArray.length; w++) {
    			if (originalArray[i] == copyArray[w]) {
    				// increase amount of times duplicate is found
    				count++;
    				// sets item to undefined
    				delete copyArray[w];
    			}
    		}
     
    		if (count > 0) {
    			var a = new Object();
    			a.value = originalArray[i];
    			a.count = count;
    			compressed.push(a);
    		}
    	}
     
    	return compressed;
    };
    
    // It should go something like this:
    
    var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
    var newArray = countArray(testArray);
    console.log(newArray);

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.