Javascript 배열에 주어진 값과 동일한 속성을 가진 객체가 포함되어 있는지 확인하는 방법은 무엇입니까?


658

나는 같은 배열을 가지고있다.

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    } //and so on goes array... 
];

Magenic이 존재하는지 확인하려면이 배열을 어떻게 확인합니까? 내가하지 않으면 루프를하고 싶지 않습니다. 잠재적으로 2 천 개의 레코드로 작업하고 있습니다.


업데이트

이것은 인기있는 게시물이기 때문에 내가 찾은 새로운 것을 나눌 것이라고 생각했습니다. @CAFxX가 이미 이것을 공유 한 것으로 보입니다! 나는 이것을 더 자주 읽어야한다. 나는 우연히 https://benfrain.com/understanding-native-javascript-array-methods/ .

vendors.filter(function(vendor){ return vendor.Name === "Magenic" })

그리고 함께 ECMAScript를 2015 은 새로운 화살표 기능을 사용하는 경우에도 간단하다 :

vendors.filter(vendor => vendor.Name === "Magenic")

겉보기에 임의의 의견을 용서하십시오. 그러나 귀하의 질문은 JSON 또는 JavaScript 배열과 관련이 있습니까?
Alex Turpin

4
@CAFxX 솔루션이 더 좋으며 선택한 솔루션을 업데이트하면 좋을 것입니다.
eMarine

1
동의했다, 일찍 보지 못했다!
David Lozzi

화살표 기능을 사용하여이를 훨씬 더 단순화 할 수 있습니다. 모든 최신 브라우저는 이것을 지원하며 더 멋지게 보입니다.
Piotr Kula

당신이지도 기능을 사용할 수 있습니다, 매우 유용한
모니르 alhussini

답변:


264

2018 편집 :이 답변은 브라우저가 배열 필터링 방법과 화살표 기능을 광범위하게 지원하기 전에 2011 년입니다. CAFxX의 답변을 살펴보십시오 .

루프가없는 배열에서 무언가를 확인하는 "마법"방법은 없습니다. 함수를 사용하더라도 함수 자체는 루프를 사용합니다. 계산 시간을 최소화하기 위해 원하는 것을 찾 자마자 루프를 벗어나는 것이 가능합니다.

var found = false;
for(var i = 0; i < vendors.length; i++) {
    if (vendors[i].Name == 'Magenic') {
        found = true;
        break;
    }
}

4
문제 없어요. 마음에 계속 키스의 솔루션은 매우 실용적이며 루프에서 저장합니다.
Alex Turpin

2
"무언가"가 있는지 여부 만 알면 플래그가 필요하지 않습니다. 배열 크기로 스캔 인덱스의 값을 확인할 수 있습니다. 이것이 작동하기 위해서는 물론 for 문 전에 인덱스 var를 선언해야합니다.
Alex

5
이러한 옵션은 현재 작동하는 것 같습니다 : vendor.forEach, vendor.filter, vendor.reduce
David Lozzi

1
JSON.stringify (vendors) .indexOf ( 'Magenic')! == -1
Last Breath

1
@LastBreath 'Magenic'는 어딘가에 다른 객체가있는 경우 쉽게 오탐을 일으킬 수 있습니다
Alex Turpin

947

다시 발명 할 필요가 없습니다 바퀴최소한 명시 적으로 루프하지 마십시오 ( 화살표 기능 사용 , 최신 브라우저에만 해당 ) :

if (vendors.filter(e => e.Name === 'Magenic').length > 0) {
  /* vendors contains the element we're looking for */
}

또는 더 나은 아직 :

if (vendors.some(e => e.Name === 'Magenic')) {
  /* vendors contains the element we're looking for */
}

편집 : 당신이 거친 브라우저와의 호환성이 필요하면 가장 좋은 방법은 다음과 같습니다.

if (vendors.filter(function(e) { return e.Name === 'Magenic'; }).length > 0) {
  /* vendors contains the element we're looking for */
}

4
@Rocket 왜 내 답변을 편집 했습니까? 중괄호가없는 구문은 완벽하게 유효한 자바 스크립트 입니다.
CAFxX

4
"lambda"구문은 여전히 ​​Chrome 16에서 작동하지 않습니다.
로켓 Hazmat

27
그것은 당신의 lousy의 정의에 달려 있습니다. 이 구문은 자바 스크립트 1.8의 일부입니다.
CAFxX

7
첫 번째 및 두 번째 예에서 여기에 사용 하는 표현 클로저 에는 비표준 이 있으므로 사용하지 마십시오! Mozilla의 경고 (링크 참조). Firefox에서만 작동했으며 이제는 더 이상 사용되지 않으며 화살표 기능 을 위해 제거됩니다 .
doppelgreener

2
@ 7hibault some는 개체 name === "Magenic"가 발견 되면 단락 될 수 있기 때문 입니다. 를 사용하면 filter배열 끝까지 각 항목을 확인하고 조건에 맞는 새 배열 항목을 만든 다음length
adiga

93

루프가 필요하지 않습니다. 생각 나는 세 가지 방법 :

Array.prototype.some ()

이것은 귀하의 질문에 대한 가장 정확한 답변입니다. 즉, "뭔가 있는지 확인하십시오"는 잘못된 결과를 암시합니다. 'Magenic'객체가 있으면 true이고, 그렇지 않으면 false입니다.

let hasMagenicVendor = vendors.some( vendor => vendor['Name'] === 'Magenic' )

Array.prototype.filter ()

하나만있는 경우에도 모든 'Magenic'객체의 배열을 반환합니다 (한 요소의 배열을 반환 함).

let magenicVendors = vendors.filter( vendor => vendor['Name'] === 'Magenic' )

이것을 부울로 강제하려고하면 빈 배열 ( 'Magenic'객체 없음)이 여전히 진실이기 때문에 작동하지 않습니다. magenicVendors.length조건부에서 사용 하십시오.

Array.prototype.find ()

첫 번째 'Magenic'객체를 반환합니다 ( undefined없는 경우).

let magenicVendor = vendors.find( vendor => vendor['Name'] === 'Magenic' );

이것은 부울 괜찮아로 강제합니다 (모든 물건이 진실하고 undefined거짓입니다).


참고 : 속성 이름이 이상한 경우 vendor.Name 대신 vendor [ "Name"]를 사용하고 있습니다.

참고 2 : 이름을 확인할 때 엄격한 동등 (===) 대신 느슨한 동등 (==)을 사용할 이유가 없습니다.


5
후드 아래에서 모두 반복됩니다. 이것들은 단순히 루핑과 연산을 수행하는 것보다 계산 속도가 느립니다.
ThePartyTurtle

: 여기뿐만 아니라 사랑을 공유하는 갈 수 stackoverflow.com/questions/21748670/... 나 같은 사람들이 더 오래된 페이지와 메이크업 가정에 탐색하지 않습니다.
ThePartyTurtle

43

받아 들여진 대답은 여전히 ​​작동하지만 이제 [Array.find][1]동일한 효과를 얻는 ECMAScript 6 기본 방법 이 있습니다.

인용 MDN :

find () 메소드는 제공된 테스트 기능을 만족하는 배열의 첫 번째 요소 값을 리턴합니다. 그렇지 않으면 undefined가 반환됩니다.

var arr = []; 
var item = {
  id: '21',
  step: 'step2',
  label: 'Banana',
  price: '19$'
};

arr.push(item);
/* note : data is the actual object that matched search criteria 
  or undefined if nothing matched */
var data = arr.find( function( ele ) { 
    return ele.id === '21';
} );

if( data ) {
 console.log( 'found' );
 console.log(data); // This is entire object i.e. `item` not boolean
}

jsfiddle 링크 보기 mozilla가 제공하는 IE 용 polyfill이 있습니다.


2
return ele.id == '2'좋은 ES6 솔루션의 경우 +1이지만 더 짧을 수 있습니다 .
거짓말 물고기

새로운 답변을
얻는

'data'의 반환 값 (ele.id가 '21'과 같은 id와 일치 할 때)이 배열 항목 자체 (이 경우 전체 항목 객체)가 될 것이라고 지적하는 것이 중요하다고 생각합니다. 데이터 변수 결과가 잘못된 값 대신 '참'또는 '거짓'이 될 것으로 예상되면 실망 할 것입니다.
adamgede

고마워! 내 임무는 조금 달랐습니다. 배열에서 Object의 인덱스를 구 push if <0 || splice(index, 1)하십시오 => 여기 약간 업데이트 된 코드가 있습니다.const index = this.selected.indexOf(this.selected.find(s => s.id == passedObj.id))
Leonid Zadorozhnykh

29

내가 할 방법은 다음과 같습니다

const found = vendors.some(item => item.Name === 'Magenic');

array.some()메소드는 기준과 일치하는 배열에 하나 이상의 값이 있는지 확인하고 부울을 리턴합니다. 여기에서 당신은 함께 갈 수 있습니다 :

if (found) {
// do something
} else {
// do something else
}

22

다음과 같이 재구성하지 않는 한 :

vendors = {
    Magenic: {
      Name: 'Magenic',
      ID: 'ABC'
     },
    Microsoft: {
      Name: 'Microsoft',
      ID: 'DEF'
    } and so on... 
};

당신이 할 수있는 if(vendors.Magnetic)

당신은 루프해야합니다


2
그는 여전히 다른 곳에서 사용하기 위해 객체 구조를 유지하고자한다면
Keith.Abramo

21

ECMAScript 6 사양에 따라을 사용할 수 있습니다 findIndex.

const magenicIndex = vendors.findIndex(vendor => vendor.Name === 'Magenic');

magenicIndex어느 개최 0(인덱스 배열이다) 또는 -1발견되지 않은 경우.


조건으로 사용 된 경우 0이 여전히 잘못된 결과로 일치한다는 것을 사람들에게 알리기 위해. 이러한 이유로 나는 논리적 인 진실 된 평가 를받을수록 find ()가 더 좋다고 생각 합니다.
dhj

15

OP가 키의 존재 여부 를 물었다 .

ES6 감소 기능을 사용하여 부울을 반환하는보다 우아한 솔루션은 다음과 같습니다.

const magenicVendorExists =  vendors.reduce((accumulator, vendor) => (accumulator||vendor.Name === "Magenic"), false);

참고 : reduce의 초기 매개 변수는 a false이며 배열에 키가 있으면 true를 반환합니다.

더 좋고 깨끗한 코드 구현에 도움이되기를 바랍니다.


1
언제부터 !! []가 false와 같습니까?
Sergey

1
잘 잡았다. 사용하여 업데이트 된 대답은 :) 감소
제이 차크라

1
이것은 잘못이다. 첫 번째 매개 변수 reducevendor객체가 아닌 누산기 입니다. 이것은 false.Name === "Magenic"모든 루프를 검사 하고 false를 반환합니다
adiga

@adiga : 수정했습니다.
Jay Chakra

1
Mirza Leka의 솔루션도 확인하십시오. 훨씬 더 우아한 솔루션.
Jay Chakra

13

당신은 실제로 물건을 들여다 보지 않고서는 할 수 없습니다.

아마도 구조를 조금 바꿔야합니다.

vendors = {
    Magenic:   'ABC',
    Microsoft: 'DEF'
};

그런 다음 조회 해시처럼 사용할 수 있습니다.

vendors['Microsoft']; // 'DEF'
vendors['Apple']; // undefined

6

너무 늦을 수 있지만 자바 스크립트 배열이 두 가지 방법을 가지고있다 someevery 부울을 반환하는 메서드가 있으며이를 달성하는 데 도움이 될 수 있습니다.

나는 some당신이 달성하려는 것에 가장 적합 하다고 생각 합니다.

vendors.some( vendor => vendor['Name'] !== 'Magenic' )

일부는 배열의 모든 객체가 주어진 조건을 만족하는지 확인합니다.

vendors.every( vendor => vendor['Name'] !== 'Magenic' )

모두는 배열의 모든 객체가 주어진 조건을 충족하는지 확인합니다.


작동하지 않습니다 const array1 = [{name:'Mike'},{name:'Alice'}]; console.log(array1.every(item => item.name !== 'Mike'));
.

죄송합니다. 친구 some는 답변을 업데이트하겠습니다.
Akinjiola Toni

5

당신은 반복해야합니다, 그 주위에 방법이 없습니다.

function seekVendor(vendors, name) {
  for (var i=0, l=vendors.length; i<l; i++) {
    if (typeof vendors[i] == "object" && vendors[i].Name === name) {
      return vendors[i];
    }
  }
}

물론 linq.js 와 같은 라이브러리를 사용하여 더 즐겁게 만들 수 있습니다 .

Enumerable.From(vendors).Where("$.Name == 'Magenic'").First();

( 데모 는 jsFiddle 참조 )

linq.js가 간단한 루프보다 빠르다는 것은 의심 스럽지만 일이 조금 더 복잡해지면 확실히 더 유연합니다.


5

배열 요소 테스트

JS는 비교적 쉽게 이것을 달성 할 수있는 배열 함수를 제공합니다. 그들은 다음과 같습니다.

  1. Array.prototype.filter: 테스트 인 콜백 함수를 가져오고 배열은 is 콜백으로 반복되고이 콜백에 따라 필터링됩니다. 새로운 필터링 된 배열이 반환됩니다.
  2. Array.prototype.some: 테스트 인 콜백 함수를 가져오고 배열은 is 콜백으로 반복되며 어떤 요소가 테스트를 통과 하면 부울 true가 리턴됩니다. 그렇지 않으면 false가 반환됩니다

구체적인 내용은 예제를 통해 가장 잘 설명됩니다.

예:

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    } //and so on goes array... 
];

// filter returns a new array, we instantly check if the length 
// is longer than zero of this newly created array
if (vendors.filter(company => company.Name === 'Magenic').length ) {
  console.log('I contain Magenic');
}

// some would be a better option then filter since it directly returns a boolean
if (vendors.some(company => company.Name === 'Magenic')) {
  console.log('I also contain Magenic');
}

브라우저 지원 :

이 두 기능은 ES6기능이며 모든 브라우저에서 지원하지는 않습니다. 이를 극복하기 위해 폴리 필을 사용할 수 있습니다. Array.prototype.someMDN 의 polyfill은 다음과 같습니다 .

if (!Array.prototype.some) {
  Array.prototype.some = function(fun, thisArg) {
    'use strict';

    if (this == null) {
      throw new TypeError('Array.prototype.some called on null or undefined');
    }

    if (typeof fun !== 'function') {
      throw new TypeError();
    }

    var t = Object(this);
    var len = t.length >>> 0;

    for (var i = 0; i < len; i++) {
      if (i in t && fun.call(thisArg, t[i], i, t)) {
        return true;
      }
    }

    return false;
  };
}


4

jquery를 사용하는 경우 grep을 활용하여 일치하는 모든 객체로 배열을 만들 수 있습니다.

var results = $.grep(vendors, function (e) {
    return e.Name == "Magenic";
});

그런 다음 결과 배열을 사용하십시오.

for (var i=0, l=results.length; i<l; i++) {
    console.log(results[i].ID);
}

3

내가 틀렸다면 바로 잡으세요. forEach이런 방법 을 사용했을 수도 있습니다 .

var found=false;
vendors.forEach(function(item){
   if(item.name === "name"){
       found=true;

   }
});

요즘 나는 단순하고 자명 한 말 때문에 익숙해 져 있습니다. 감사합니다.


1
참고 : 여기에 반품을 사용하지 않음
Edison

2

이 작업을 시도해 볼 수 있습니다.

const _ = require('lodash');

var arr = [
  {
    name: 'Jack',
    id: 1
  },
  {
    name: 'Gabriel',
    id: 2
  },
  {
    name: 'John',
    id: 3
  }
]

function findValue(arr,value) {
  return _.filter(arr, function (object) {
    return object['name'].toLowerCase().indexOf(value.toLowerCase()) >= 0;
  });
}

console.log(findValue(arr,'jack'))
//[ { name: 'Jack', id: 1 } ]

글쎄, 이것은 정말 오래된 질문이며 현재 업데이트가 이미 최고의 솔루션을 가지고 있다고 생각합니다.
Federico Galfione

1

lodash 를 사용할 수 있습니다 . lodash 라이브러리가 애플리케이션에 비해 너무 무거 우면 불필요한 기능을 사용하지 않는 청크를 고려하십시오.

let newArray = filter(_this.props.ArrayOne, function(item) {
                    return find(_this.props.ArrayTwo, {"speciesId": item.speciesId});
                });

이것은 이것을하는 한 가지 방법 일뿐입니다. 다른 하나는 다음과 같습니다.

var newArray=  [];
     _.filter(ArrayOne, function(item) {
                        return AllSpecies.forEach(function(cItem){
                            if (cItem.speciesId == item.speciesId){
                            newArray.push(item);
                          }
                        }) 
                    });

console.log(arr);

위의 예제는 다음과 같은 라이브러리 를 사용하지 않고도 다시 작성할 수 있습니다 .

var newArray=  [];
ArrayOne.filter(function(item) {
                return ArrayTwo.forEach(function(cItem){
                    if (cItem.speciesId == item.speciesId){
                    newArray.push(item);
                  }
                }) 
            });
console.log(arr);

내 대답이 도움이 되길 바랍니다.


1

여기에 많은 답변이 좋고 아주 쉽습니다. 그러나 객체 배열에 고정 값 세트가 있으면 아래 트릭을 사용할 수 있습니다.

객체의 모든 이름을 매핑하십시오.

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    }
];

var dirtyObj = {}
for(var count=0;count<vendors.length;count++){
   dirtyObj[vendors[count].Name] = true //or assign which gives you true.
}

이제이 dirtyObj를 반복없이 사용할 수 있습니다.

if(dirtyObj[vendor.Name]){
  console.log("Hey! I am available.");
}

1

한 객체를 다른 객체와 비교하기 위해 for 루프 (객체를 반복하는 데 사용)와 some ()을 결합합니다. 배열이 범위를 벗어나는 것에 대해 걱정할 필요가 없으므로 일부 코드가 저장됩니다. .some에 대한 설명서는 여기 에서 찾을 수 있습니다 .

var productList = [{id: 'text3'}, {id: 'text2'}, {id: 'text4', product: 'Shampoo'}]; // Example of selected products
var theDatabaseList = [{id: 'text1'}, {id: 'text2'},{id: 'text3'},{id:'text4', product: 'shampoo'}];    
var  objectsFound = [];

for(let objectNumber in productList){
    var currentId = productList[objectNumber].id;   
    if (theDatabaseList.some(obj => obj.id === currentId)) {
        // Do what you need to do with the matching value here
        objectsFound.push(currentId);
    }
}
console.log(objectsFound);

한 객체를 다른 객체와 비교하는 다른 방법은 Object.keys (). length와 함께 중첩 for 루프를 사용하여 배열의 객체 양을 얻는 것입니다. 아래 코드 :

var productList = [{id: 'text3'}, {id: 'text2'}, {id: 'text4', product: 'Shampoo'}]; // Example of selected products
var theDatabaseList = [{id: 'text1'}, {id: 'text2'},{id: 'text3'},{id:'text4', product: 'shampoo'}];    
var objectsFound = [];

for(var i = 0; i < Object.keys(productList).length; i++){
        for(var j = 0; j < Object.keys(theDatabaseList).length; j++){
        if(productList[i].id === theDatabaseList[j].id){
            objectsFound.push(productList[i].id);
        }       
    }
}
console.log(objectsFound);

정확한 질문에 대답하기 위해 객체에서 값을 검색하는 경우 단일 루프를 사용할 수 있습니다.

var vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    } 
];

for(var ojectNumbers in vendors){
    if(vendors[ojectNumbers].Name === 'Magenic'){
        console.log('object contains Magenic');
    }
}

0

또는 다음을 수행 할 수 있습니다.

const find = (key, needle) => return !!~vendors.findIndex(v => (v[key] === needle));

1
왜 그가 그렇게 할 수 있는지 더 잘 말할 것입니다
Azzabi Haythem

0

var without2 = (arr, args) => arr.filter(v => v.id !== args.id); 예:

without2([{id:1},{id:1},{id:2}],{id:2})

결과 : without2 ([{id : 1}, {id : 1}, {id : 2}], {id : 2})


[{ID : : : 1}, {1 ID}] 당신이 결과라고 의미 생각
이삭 박

0
const a = [{one:2},{two:2},{two:4}]
const b = a.filter(val => "two" in val).length;
if (b) {
   ...
}

3
설명과 설명을 제공하고 제공 한 예제가 작동하는지 확인하십시오. 필터는 원래 배열을 변경하지 않고 복제합니다.
Moshe Simantov

-1

이 문제를 해결하기위한 나의 접근법은 ES6를 사용하고 우리를 점검하는 기능을 만드는 것입니다. 이 기능의 장점은 프로젝트가 주어진 객체의 배열을 확인하기 위해 밖으로을 통해 재사용 할 수 있다는 것입니다 key과를 value확인합니다.

충분한 이야기, 코드를 보자

정렬

const ceos = [
  {
    name: "Jeff Bezos",
    company: "Amazon"
  }, 
  {
    name: "Mark Zuckerberg",
    company: "Facebook"
  }, 
  {
    name: "Tim Cook",
    company: "Apple"
  }
];

함수

const arrayIncludesInObj = (arr, key, valueToCheck) => {
  let found = false;

  arr.some(value => {
    if (value[key] === valueToCheck) {
      found = true;
      return true; // this will break the loop once found
    }
  });

  return found;
}

전화 / 사용

const found = arrayIncludesInObj(ceos, "name", "Tim Cook"); // true

const found = arrayIncludesInObj(ceos, "name", "Tim Bezos"); // false

-4

오히려 정규식으로 갈 것입니다.

코드가 다음과 같다면

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    }
];

나는 추천 할 것이다

/"Name":"Magenic"/.test(JSON.stringify(vendors))

23
어떤 사람들은 문제에 직면했을 때 "정규 표현을 사용할 것입니다."라고 생각합니다. 이제 두 가지 문제가 있습니다.
Craicerjack

무언가를 할 수 있다고해서 반드시 아래에 제출해야한다는 의미는 아닙니다.
Liam
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.