arrays js array - 배열에 JavaScript로 객체가 포함되어 있는지 확인하려면 어떻게합니까?





15 Answers

업데이트 : @orip은 주석에서 언급 했으므로 2008 년에 링크 된 벤치 마크가 수행되었으므로 최신 브라우저에서는 결과가 적절하지 않을 수 있습니다. 그러나 어쨌든 비 현대적인 브라우저를 지원하려면이 기능이 필요하며 이후로 업데이트되지 않았을 것입니다. 항상 스스로 테스트 해보십시오.

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

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

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

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
functions refer record

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

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

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

이 작업을 수행하는 더 우수하고 간결한 방법이 있습니까?

질문과 매우 밀접하게 관련 되어 있습니다 JavaScript Array에서 항목을 찾는 가장 좋은 방법은 무엇입니까? indexOf 사용하여 배열에서 객체를 찾는 문제를 해결합니다.




ECMAScript 7은 array.includes(value) 도입했습니다.

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

[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

Strict Equality Comparison 을 사용하는 indexOf 와는 달리 SameValueZero 동등 알고리즘을 사용하여 비교합니다. 즉, 배열에 NaN 포함되어 있는지 감지 할 수 있습니다.

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

또한 indexOf 와는 달리 indexOf includes 누락 된 인덱스를 건너 뛰지 않습니다.

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

현재는 여전히 초안이지만 모든 브라우저에서 작동하도록 polyfill 될 수 있습니다.




Array.indexOfJavaScript 1.6 호환 구현은 다음과 같습니다.

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



최상위 답변은 기본 유형을 가정하지만 배열에 특성이있는 객체가 있는지 알아 보려면 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
}

* jamess가 코멘트에서 지적했듯이 2018 년 9 월 현재 Array.prototype.some() 이 완전히 지원됩니다. caniuse.com 지원 테이블







나는 다음을 사용한다.

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

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

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



희망보다 빠른 양방향 indexOf / lastIndexOf 대안

2015

새로운 메소드가 array.includes(value) 있지만, 지원은 기본적으로 현재는 0입니다.

느린 indexOf / lastIndexOf 함수를 대체 할 길을 생각하고 있습니다.

공연자의 길은 이미 발견되었고, 가장 많이 찾는 답을 보았습니다. 그 중에서 내가 가장 빨리해야 할 @Damir Zekic이 게시 한 contains 함수를 선택했습니다. 그러나 그것은 또한 벤치 마크가 2008 년에 나온 것이기 때문에 구식이라고합니다.

나는 또한 while 이상 for 선호하지만 특정 이유가 없으면 for 루프를 사용하여 함수를 작성하지 못했습니다. 그것도 while -- 할 수 있습니다 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 항목이있는 배열을 만들었습니다.

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

이 흥미로운 것을 발견하고 성능을 시험해 보시기 바랍니다.

참고 : 보시다시피 indexOf 및 lastIndexOf 출력을 반영하도록 contains 함수를 약간 수정했습니다 (기본적으로 index 에서는 false 이고 -1 false ). 그건 그걸 해치지 않아야 해.

배열 프로토 타입 변형

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

이것이 어떻게 가능한지?

배열에서 반사 된 인덱스를 얻는 간단한 계산은 너무 간단하므로 실제 루프 반복을 수행하는 것보다 2 배 빠르다고 생각합니다.

반복마다 세 번씩 수행하는 복잡한 예제가 있지만 코드의 속도 저하를 초래하는 더 긴 계산에서만 가능합니다.

http://jsperf.com/bidirectionalindexof/2




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

발견되면 배열 인덱스를 반환하고, 발견되지 않으면 -1을 반환합니다.




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




array.indexOf(x)!=-1 이 이것을 수행하는 가장 간결한 방법 인 반면 array.indexOf(x)!=-1 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에 두 줄로 저장할 수 있습니다. 나중에 배열을 편집하기로 선택하면 잘못된 결과가 나타납니다. 예를 들어 파이썬과 달리이 상태를 유지하게하십시오.)




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

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.indexOfArray.includes (여기에서 대부분의 답변뿐만 아니라)는 값이 아닌 참조로만 비교됩니다.

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

보너스

최적화되지 않은 ES6 one-liner :

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

참고 : 키를 같은 순서로 사용하면 개체를 값으로 비교하면 안전합니다. 먼저 다음과 같은 패키지로 키를 정렬 할 수 있습니다. https://www.npmjs.com/package/sort-keys

perf 최적화로 contains 함수를 업데이트했습니다. 그것을 지적 해 주셔서 감사합니다.




Prototype의 기능은 다음과 같습니다.

/**
 *  Array#indexOf(item[, offset = 0]) -> Number
 *  - item (?): A value that may or may not be in the array.
 *  - offset (Number): The number of initial items to skip before beginning the
 *      search.
 *
 *  Returns the position of the first occurrence of `item` within the array &mdash; or
 *  `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
  i || (i = 0);
  var length = this.length;
  if (i < 0) i = length + i;
  for (; i < length; i++)
    if (this[i] === item) return i;
  return -1;
}

또한 그들이 그것을 연결하는 방법을 보려면 here 를 참조 here .




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



OK, 결과를 얻기 위해 코드를 최적화 할 수 있습니다! 이 작업을 수행하는 데는 여러 가지 방법이 있지만 더 깨끗하고 좋은 방법이 있지만 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;
}



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

이것을 사용하지 마십시오.

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






Related