배열에 JavaScript의 객체가 포함되어 있는지 어떻게 확인합니까?
-
04-07-2019 - |
문제
JavaScript 배열에 객체가 포함되어 있는지 확인하는 가장 간결하고 효율적인 방법은 무엇입니까?
이것이 제가 그것을하는 유일한 방법입니다.
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
이것을 달성하는 더 좋고 간결한 방법이 있습니까?
이것은 스택 오버플로 질문과 매우 밀접한 관련이 있습니다 JavaScript 배열에서 항목을 찾는 가장 좋은 방법? 이는 배열에서 개체를 찾는 것을 다루고 있습니다 indexOf
.
해결책
현재 브라우저가 있습니다 Array#includes
, 무엇을합니다 바로 그거죠 저것, 널리 지원됩니다, 그리고 a 폴리 필 구형 브라우저의 경우.
> ['joe', 'jane', 'mary'].includes('jane');
true
당신은 또한 사용할 수 있습니다 Array#indexOf
, 직접적이지는 않지만 날짜가없는 브라우저에는 폴리 필이 필요하지 않습니다.
jQuery 제안 $.inArray
, 기능적으로 동일합니다 Array#indexOf
.
aUNDSCORE.JS, JavaScript 유틸리티 라이브러리, 제안 _.contains(list, value)
, 별명 _.include(list, value)
, 둘 다 사용합니다 인덱스 내부적으로 JavaScript 배열을 통과 한 경우.
일부 다른 프레임 워크는 비슷한 방법을 제공합니다.
- 도조 툴킷 :
dojo.indexOf(array, value, [fromIndex, findLast])
- 원기:
array.indexOf(value)
- mootools :
array.indexOf(value)
- Mochikit :
findValue(array, value)
- MS Ajax :
array.indexOf(value)
- 내선 :
Ext.Array.contains(array, value)
- Lodash :
_.includes(array, value, [from])
(이다_.contains
이전 4.0.0) - ECMAScript 2016 :
array.includes(value)
일부 프레임 워크는 이것을 함수로 구현하는 반면 다른 프레임 워크는 기능을 배열 프로토 타입에 추가합니다.
다른 팁
업데이트 : @ORIP가 의견에 언급했듯이 링크 된 벤치 마크는 2008 년에 수행되었으므로 최신 브라우저와 관련이 없을 수 있습니다. 그러나 어쨌든 비 현대식 브라우저를 지원하기 위해서는이 문제가 필요하며 그 이후로 업데이트되지 않았을 것입니다. 항상 자신을 테스트하십시오.
다른 사람들이 말했듯이, 배열을 통한 반복이 아마도 가장 좋은 방법 일 것입니다. 입증되었습니다 그것은 감소하는 것입니다 while
루프는 JavaScript에서 반복하는 가장 빠른 방법입니다. 따라서 다음과 같이 코드를 다시 작성할 수 있습니다.
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
indexOf
어쩌면 "ECMA-262 표준에 대한 JavaScript 확장자 일 수도 있습니다. 따라서 표준의 다른 구현에는 존재하지 않을 수 있습니다."
예시:
[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1
afaics 마이크로 소프트 ~ 아니다 일종의 대안을 제공합니다 이에는 인터넷 익스플로러 (및 지원하지 않는 기타 브라우저의 배열에 유사한 기능을 추가 할 수 있습니다. indexOf
) 원한다면, a 빠른 Google 검색이 공개됩니다 (예를 들어, 이 하나).
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 평등 알고리즘. 즉, 배열에 A가 포함 된 경우 감지 할 수 있음을 의미합니다. NaN
:
[1, 2, NaN].includes(NaN); // true
또한와 다릅니다 indexOf
, includes
누락 된 인덱스를 건너 뛰지 않습니다.
new Array(5).includes(undefined); // true
현재는 여전히 초안이지만 가능합니다 폴리 채식 모든 브라우저에서 작동합니다.
b
가치입니다 a
배열입니다. 돌아옵니다 true
또는 false
:
function(a, b) {
return a.indexOf(b) != -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 지원 테이블
여기에 있습니다 JavaScript 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;
};
}
사용:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
// Usage
if(isInArray(my_array, "my_value"))
{
//...
}
JavaScript 확장 Array
객체는 새로운 속성 (사용자 정의 방법)을 for-in
기존 스크립트를 깨뜨릴 수있는 루프. 몇 년 전 저자의 저자 원기 도서관은 이런 종류의 것을 제거하기 위해 라이브러리 구현을 리엔지니어링해야했습니다.
페이지에서 실행중인 다른 JavaScript와의 호환성에 대해 걱정할 필요가 없다면 이동하십시오. 그렇지 않으면 더 어색하지만 안전한 독립형 기능 솔루션을 추천합니다.
상자를 잠시 생각하면,이 전화를 여러 번 만들고 있다면 사용하는 것이 훨씬 더 효율적입니다. 연관 배열 해시 함수를 사용하여 조회를 수행하는 맵.
https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/map
짧막 한 농담:
function contains(arr, x) {
return arr.filter(function(elem) { return elem == x }).length > 0;
}
다음을 사용합니다.
Array.prototype.contains = function (v) {
return this.indexOf(v) > -1;
}
var a = [ 'foo', 'bar' ];
a.contains('foo'); // true
a.contains('fox'); // false
function contains(a, obj) {
return a.some(function(element){return element == obj;})
}
Array.prototype.some () 5 판에서 ECMA-262 표준에 추가되었습니다.
희망적으로 더 빠른 양방향 indexOf
/ lastIndexOf
대안
2015
새로운 방법으로 포함 매우 좋습니다. 현재 지원은 기본적으로 0입니다.
느린 인덱스/lastindexof 함수를 대체 할 방법을 생각하고 있었던 것은 오랜 시간입니다.
최고의 답변을 보면서 성능적인 방식이 이미 발견되었습니다. 내가 선택한 사람들로부터 contains
@damir Zekic에 의해 게시 된 기능. 그러나 벤치 마크는 2008 년부터 구식이라고 말합니다.
나도 선호합니다 while
~ 위에 for
, 그러나 특정한 이유가 아니기 때문에 나는 for loop으로 함수를 쓰는 것을 끝냈습니다. a while --
.
배열을하는 동안 배열의 양쪽을 확인하면 반복이 훨씬 느려 있는지 궁금했습니다. 분명히 아니요, 따라서이 기능은 최상위 투표보다 약 2 배 빠릅니다. 분명히 그것은 또한 원주민보다 빠릅니다. 이것은 당신이 검색하는 값이 배열의 시작 또는 끝에 있는지 알지 못하는 실제 환경에서.
당신이 방금 값으로 배열을 밀었을 때, lastIndexof를 사용하는 것은 아마도 최상의 솔루션 일 것입니다. 그러나 큰 배열을 여행해야하고 결과가 어디에나있을 수 있다면, 이것은 물건을 더 빨리 만들기위한 견고한 솔루션이 될 수 있습니다.
양방향 지수/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');
함수는 참 또는 거짓 또는 객체, 문자열 또는 그 밖의 모든 것을 반환하도록 쉽게 수정할 수 있습니다.
그리고 여기에 있습니다 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');
이것이 어떻게 가능한지?
배열에서 반사 된 인덱스를 얻는 간단한 계산은 너무 간단하여 실제 루프 반복을 수행하는 것보다 두 배 더 빠릅니다.
다음은 반복 당 세 가지 검사를 수행하는 복잡한 예는 있지만, 이는 더 긴 계산으로 만 가능하여 코드의 둔화를 유발합니다.
JavaScript 1.6 이상 (Firefox 1.5 이상)을 사용하는 경우 사용할 수 있습니다. Array.indexof. 그렇지 않으면, 나는 당신이 당신의 원래 코드와 비슷한 것으로 끝날 것이라고 생각합니다.
function inArray(elem,array)
{
var len = array.length;
for(var i = 0 ; i < len;i++)
{
if(array[i] == elem){return i;}
}
return -1;
}
찾은 경우 배열 인덱스를 반환하거나 찾을 수없는 경우 -1
우리는이 스 니펫을 사용합니다 (물체, 배열, 문자열과 함께 작동) :
/*
* @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
Lodash를 사용하십시오 약간 기능.
간결하고 정확하며 크로스 플랫폼 지원이 뛰어납니다.
허용 된 답변은 요구 사항을 충족하지 않습니다.
요구 사항 : JavaScript 배열에 객체가 포함되어 있는지 확인하는 가장 간결하고 효율적인 방법을 권장합니다.
받아 들여진 답변 :
$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1
내 추천 :
_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true
메모:
$ .inarray는 a 스칼라 값은 스칼라 배열에 존재합니다 ...
$.inArray(2, [1,2])
> 1
... 그러나 질문은 물체 배열에 포함되어 있습니다.
스칼라와 물체를 모두 처리하려면 다음을 수행 할 수 있습니다.
(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
모든 현대식 브라우저에서 작동하는 솔루션 :
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 1 라이너 :
[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true
참고 : 키가 동일한 순서 인 경우 객체를 값으로 비교하는 것이 더 잘 작동하므로 안전하기 위해서는 이와 같은 패키지로 키를 먼저 정렬 할 수 있습니다. https://www.npmjs.com/package/sort-keys
업데이트 contains
Perf 최적화로 기능합니다. 감사 itinance 그것을 지적하기 위해.
하는 동안 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})
(불행히도, 배열을 만들 수는 있지만 배열을 "동결"하고 hashtable을 this._cache를 두 줄로 보관할 수 있지만 나중에 배열을 편집하기로 선택하면 잘못된 결과를 얻을 수 있습니다. JavaScript는 후크가 충분하지 않습니다. 예를 들어 파이썬과 달리이 상태를 유지하겠습니다.)
ECMAScript 6에는 찾기에 대한 우아한 제안이 있습니다.
찾기 메소드는 콜백이 실제 값을 반환하는 곳을 찾을 때까지 배열에있는 각 요소에 대해 콜백 함수를 한 번 실행합니다. 그러한 요소가 발견되면 해당 요소의 값을 즉시 반환합니다. 그렇지 않으면, 찾기 반품을 정의하지 않습니다. 콜백은 값을 할당 한 배열의 인덱스에 대해서만 호출됩니다. 삭제되었거나 값이 할당되지 않은 인덱스에 대해서는 호출되지 않습니다.
여기에 있습니다 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;
}
});
}
사용:
var myArray = ['yellow', 'orange', 'red'] ;
alert(!!~myArray.indexOf('red')); //true
정확히 무엇을 아는 것 tilde
~
이 시점 에서이 질문을 참조하십시오 틸데는 표현보다 우선 할 때 무엇을합니까?.
방법은 다음과 같습니다 프로토 타입이 그렇게합니다:
/**
* 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 — 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;
}
또한 참조하십시오 여기 그들이 그것을 연결하는 방법에 대해.
좋아, 당신은 그냥 할 수 있습니다 최적화하십시오 결과를 얻기위한 코드!
더 깨끗하고 더 나은이 작업을 수행하는 방법에는 여러 가지가 있지만 패턴을 얻고 사용에 적용하고 싶었습니다. 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;
}
사용:
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);
}
나는 그것이 가장 좋은 방법이 아니라는 것을 알고 있지만, 객체들 사이를 상호 작용하는 기본 Icomponday 방법이 없기 때문에 배열에서 두 엔티티를 비교할 수있는만큼 가깝다고 생각합니다. 또한, 배열 객체를 확장하는 것은 현명한 일이 아닐 수도 있지만 때로는 괜찮습니다 (당신이 그것을 알고 있다면 트레이드 오프).
하나는 사용할 수 있습니다 세트 "has ()"방법이 있습니다.
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'));
이 트릭을 사용할 수도 있습니다.
var arrayContains = function(object) {
return (serverList.filter(function(currentObject) {
if (currentObject === object) {
return currentObject
}
else {
return false;
}
}).length > 0) ? true : false
}
- 어느 쪽이든
Array.indexOf(Object)
. - ECMA 7을 사용하면 사용할 수 있습니다
Array.includes(Object)
. ECMA 6을 사용하면 사용할 수 있습니다
Array.find(FunctionName)
어디FunctionName
배열에서 객체를 검색하는 사용자 정의 함수입니다.도움이 되었기를 바랍니다!
비슷한 점 : "Search Lambda"로 첫 번째 요소를 찾습니다.
Array.prototype.find = function(search_lambda) {
return this[this.map(search_lambda).indexOf(true)];
};
용법:
[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4
커피 스크립트에서도 마찬가지 :
Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]