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




index isinarray (25)

다른 사람들이 언급했듯이 Array.indexOf 를 사용할 수 있지만 모든 브라우저에서 사용할 수있는 것은 아닙니다. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf 의 코드는 이전 브라우저에서도 동일하게 작동합니다.

indexOf는 최근 ECMA-262 표준에 추가되었습니다. 따라서 모든 브라우저에 존재하지 않을 수 있습니다. 스크립트의 시작 부분에 다음 코드를 삽입하여이 문제를 해결할 수 있습니다. 기본적으로 지원하지 않는 구현에서 indexOf를 사용할 수 있습니다. 이 알고리즘은 Object, TypeError, Number, Math.floor, Math.abs 및 Math.max가 원래 값을 가진다고 가정하고 ECMA-262, 5th edition에 명시된 알고리즘과 동일합니다.

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
        "use strict";
        if (this == null) {
            throw new TypeError();
        }
        var t = Object(this);
        var len = t.length >>> 0;
        if (len === 0) {
            return -1;
        }
        var n = 0;
        if (arguments.length > 1) {
            n = Number(arguments[1]);
            if (n != n) { // shortcut for verifying if it's NaN
                n = 0;
            } else if (n != 0 && n != Infinity && n != -Infinity) {
                n = (n > 0 || -1) * Math.floor(Math.abs(n));
            }
        }
        if (n >= len) {
            return -1;
        }
        var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
        for (; k < len; k++) {
            if (k in t && t[k] === searchElement) {
                return k;
            }
        }
        return -1;
    }
}

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

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

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

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

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



용도:

Array.prototype.contains = function(x){
  var retVal = -1;

  // x is a primitive type
  if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}

  // x is a function
  else if(typeof x =="function") for(var ix in this){
    if((this[ix]+"")==(x+"")) retVal = ix;
  }

  //x is an object...
  else {
    var sx=JSON.stringify(x);
    for(var ix in this){
      if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
    }
  }

  //Return False if -1 else number if numeric otherwise string
  return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}

나는 그것이가는 가장 좋은 방법은 아니지만, 객체간에 상호 작용할 수있는 고유 한 IComparable 방법이 없기 때문에 이것은 배열에서 두 엔티티를 비교할 수있는만큼 가깝습니다. 또한, Array 객체를 확장하는 것이 현명한 방법이 아닌 경우도 있지만, 때로는 괜찮습니다 (잘 알고있는 경우).


b 는 값이고 a 는 배열입니다. true 또는 false 반환 true .

function(a, b) {
    return a.indexOf(b) != -1
}

lodash의 some 기능을 사용하십시오.

간결하고 정확하며 훌륭한 크로스 플랫폼을 지원합니다.

허용 된 답변은 요구 사항을 충족하지 못합니다.

요구 사항 : 자바 스크립트 배열에 객체가 포함되어 있는지 확인하는 가장 간결하고 효율적인 방법을 제안하십시오.

수락 된 답변 :

$.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)

용도:

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

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

업데이트 : @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

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

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

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


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에 두 줄로 저장할 수 있습니다. 나중에 배열을 편집하기로 선택하면 잘못된 결과가 나타납니다. 예를 들어 파이썬과 달리이 상태를 유지하게하십시오.)



현재 브라우저에는 Array#includes 가 있습니다. 이 기능은 광범위하게 지원 되며 구형 브라우저 용 polyfill 을 포함합니다.

> ['joe', 'jane', 'mary'].includes('jane');
true 

Array#indexOf 사용할 수도 있습니다 Array#indexOf 는 덜 직접적이지만 오래된 브라우저에서는 Polyfills가 필요하지 않습니다.

jQuery는 $.inArray 제공 $.inArray , 이는 Array#indexOf 와 기능적으로 동일합니다.

JavaScript 유틸리티 라이브러리 인 underscore.js_.contains(list, value) , 별칭 _.include(list, value) 를 제공하며 JavaScript 배열을 전달할 경우 indexOf 내부적으로 사용합니다.

다른 일부 프레임 워크는 비슷한 방법을 제공합니다.

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


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

배열에 객체가 있는지 반복적으로 확인하는 경우에는

  1. 배열에 삽입 정렬 을 수행하여 배열을 항상 정렬 된 상태로 유지합니다 (새 객체를 올바른 위치에 배치).
  2. 개체를 remove + 정렬 된 삽입 작업으로 업데이트하고
  3. contains(a, obj) 에서 바이너리 검색 룩업을 사용하십시오.

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


나는 다음을 사용한다.

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

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

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

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

function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

Array.prototype.some() 이 5 판의 ECMA-262 표준에 추가되었습니다.


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


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

희망보다 빠른 양방향 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을 반환합니다.


ECMAScript 6에는 find에 대한 우아한 제안이 있습니다.

find 메서드는 콜백 함수가 true 값을 반환 할 때까지 배열에있는 각 요소에 대해 한 번씩 콜백 함수를 실행합니다. 이러한 요소가 발견되면 find는 해당 요소의 값을 즉시 반환합니다. 그렇지 않으면 find는 undefined를 반환합니다. 콜백은 값이 할당 된 배열의 인덱스에 대해서만 호출됩니다. 삭제되었거나 값이 할당 된 적이없는 인덱스에 대해서는 호출되지 않습니다.

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

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

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

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 .


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

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 함수를 업데이트했습니다. 그것을 지적 해 주셔서 감사합니다.


6 살짜리 아이에게 어떻게 설명 할 수 있을까요?

어른들이 집을 소유 할 수있는 방법을 알고 집에 전화합니까? 엄마가 아이를 가질 때, 아이는 정말로 아무것도 소유하지 않습니다. 그렇죠? 그러나 부모는 집을 소유하고 있으므로 다른 사람이 자녀에게 "집이 어디 있습니까?"라고 묻는다면 "그 집!"이라고 대답하고 부모의 집을 가리킬 수 있습니다. "폐쇄 (Closure)"는 자녀가 항상 집을 소유하고있는 부모 인 경우에도 항상 (해외에 있더라도) 집에 있다고 말할 수있는 능력입니다.





javascript arrays browser