etc./StackOverFlow

객체 배열에서 속성 값을 배열로 추출

청렴결백한 만능 재주꾼 2022. 2. 27. 12:39
반응형

질문자 :hyde


다음 구조의 JavaScript 객체 배열이 있습니다.

 objArray = [ { foo: 1, bar: 2}, { foo: 3, bar: 4}, { foo: 5, bar: 6} ];

각 객체에서 필드를 추출하고 값이 포함된 배열을 얻고 싶습니다. 예를 들어 foo 필드는 array [ 1, 3, 5 ] 합니다.

이 간단한 접근 방식으로 이 작업을 수행할 수 있습니다.

 function getFields(input, field) { var output = []; for (var i=0; i < input.length ; ++i) output.push(input[i][field]); return output; } var result = getFields(objArray, "foo"); // returns [ 1, 3, 5 ]

사용자 정의 유틸리티 기능이 필요하지 않도록 이 작업을 수행하는 더 우아하거나 관용적인 방법이 있습니까?


제안된 복제 에 대한 참고 사항은 단일 객체 를 배열로 변환하는 방법을 다룹니다.



이를 달성하는 더 짧은 방법은 다음과 같습니다.

 let result = objArray.map(a => a.foo);

또는

 let result = objArray.map(({ foo }) => foo)

Array.prototype.map() 확인할 수도 있습니다.


Jalasem

예, 하지만 JavaScript의 ES5 기능에 의존합니다. 즉, IE8 이상에서는 작동하지 않습니다.

 var result = objArray.map(function(a) {return a.foo;});

ES6 호환 JS 인터프리터에서는 간결함을 위해 화살표 기능을 사용할 수 있습니다.

 var result = objArray.map(a => a.foo);

Array.prototype.map 문서


Niet the Dark Absol

JS 전용 솔루션에 대해 말하면서, 우아하지 않을 수 있지만 간단한 인덱스 for 루프가 대안보다 성능이 더 우수하다는 것을 알았습니다.

100000개의 요소 배열에서 단일 속성 추출(jsPerf를 통해)

기존 for 루프 368 Ops/sec

 var vals=[]; for(var i=0;i<testArray.length;i++){ vals.push(testArray[i].val); }

ES6 for..of 루프 303 Ops/sec

 var vals=[]; for(var item of testArray){ vals.push(item.val); }

Array.prototype.map 19 Ops/sec

 var vals = testArray.map(function(a) {return a.val;});

TL;DR - .map()은 느리지만 성능보다 가독성이 더 중요하다고 생각되면 자유롭게 사용하십시오.

편집 #2: 2019년 6월 - jsPerf 링크가 깨져 제거되었습니다.


pscl

Lodash의 _.pluck() 함수 또는 Underscore의 _.pluck() 함수를 확인하십시오. 둘 다 단일 함수 호출에서 원하는 것을 정확히 수행합니다!

 var result = _.pluck(objArray, 'foo');

업데이트: _.pluck() 은 Lodash v4.0.0에서 제거되었으며 Niet의 답변 과 유사한 것과 함께 _.map() 되었습니다. _.pluck() 은 Underscore 에서 계속 사용할 수 있습니다 .

업데이트 2: Mark가 주석에서 지적했듯이 Lodash v4와 4.3 사이 어딘가에 이 기능을 다시 제공하는 새로운 기능이 추가되었습니다. _.property() 는 객체의 속성 값을 가져오는 함수를 반환하는 약식 함수입니다.

또한 _.map() 사용하면 문자열을 두 번째 매개변수로 전달할 수 있으며, 이 매개변수는 _.property() 전달됩니다. 결과적으로 다음 두 줄은 위의 Lodash 4 이전 코드 샘플과 동일합니다.

 var result = _.map(objArray, 'foo'); var result = _.map(objArray, _.property('foo'));

_.property() , 따라서 _.map() 을 사용하면 하위 속성에 액세스하기 위해 점으로 구분된 문자열 또는 배열을 제공할 수도 있습니다.

 var objArray = [ { someProperty: { aNumber: 5 } }, { someProperty: { aNumber: 2 } }, { someProperty: { aNumber: 9 } } ]; var result = _.map(objArray, _.property('someProperty.aNumber')); var result = _.map(objArray, _.property(['someProperty', 'aNumber']));

위의 예에서 두 _.map() [5, 2, 9] 반환합니다.

함수형 프로그래밍에 조금 더 관심이 있다면 다음과 같은 Ramda의 R.pluck() 함수를 살펴보세요.

 var result = R.pluck('foo')(objArray); // or just R.pluck('foo', objArray)

tomb

브라우저 간 보증을 위해 lodash 또는 밑줄과 같은 일종의 라이브러리를 사용하는 것이 좋습니다.

Lodash에서는 다음 방법으로 배열의 속성 값을 얻을 수 있습니다.

 _.map(objArray,"foo")

그리고 밑줄에서

 _.pluck(objArray,"foo")

둘 다 돌아올 것이다

 [1, 2, 3]

Tejas Patel

Array.prototype.map 사용:

 function getFields(input, field) { return input.map(function(o) { return o[field]; }); }

ES5 이전 브라우저용 shim은 위의 링크를 참조하세요.


Alnitak

ES6에서는 다음을 수행할 수 있습니다.

 const objArray = [{foo: 1, bar: 2}, {foo: 3, bar: 4}, {foo: 5, bar: 6}] objArray.map(({ foo }) => foo)

Yuxuan Chen

객체 배열에서 다른 필드를 수집하는 예

 let inputArray = [ { id: 1, name: "name1", value: "value1" }, { id: 2, name: "name2", value: "value2" }, ]; let ids = inputArray.map( (item) => item.id); let names = inputArray.map((item) => item.name); let values = inputArray.map((item) => item.value); console.log(ids); console.log(names); console.log(values);

결과 :

 [ 1, 2 ] [ 'name1', 'name2' ] [ 'value1', 'value2' ]

Jafar Karuthedath

map 는 객체 목록에서 '열'을 선택하는 적절한 솔루션이지만 단점이 있습니다. 열이 있는지 여부를 명시적으로 확인하지 않으면 오류가 발생하고 (기껏해야) undefined 제공합니다. 나는 단순히 속성을 무시하거나 기본값으로 설정할 수 reduce

 function getFields(list, field) { // reduce the provided list to an array only containing the requested field return list.reduce(function(carry, item) { // check if the item is actually an object and does contain the field if (typeof item === 'object' && field in item) { carry.push(item[field]); } // return the 'carry' (which is the list of matched field values) return carry; }, []); }

jsbin 예제

이것은 제공된 목록의 항목 중 하나가 개체가 아니거나 필드를 포함하지 않는 경우에도 작동합니다.

항목이 개체가 아니거나 필드를 포함하지 않는 경우 기본값을 협상하여 보다 유연하게 만들 수 있습니다.

 function getFields(list, field, otherwise) { // reduce the provided list to an array containing either the requested field or the alternative value return list.reduce(function(carry, item) { // If item is an object and contains the field, add its value and the value of otherwise if not carry.push(typeof item === 'object' && field in item ? item[field] : otherwise); // return the 'carry' (which is the list of matched field values) return carry; }, []); }

jsbin 예제

반환된 배열의 길이가 제공된 배열과 같기 때문에 이것은 map과 동일합니다. (이 경우에서 map A가보다 약간 저렴 reduce )

 function getFields(list, field, otherwise) { // map the provided list to an array containing either the requested field or the alternative value return list.map(function(item) { // If item is an object and contains the field, add its value and the value of otherwise if not return typeof item === 'object' && field in item ? item[field] : otherwise; }, []); }

jsbin 예제

그리고 가장 유연한 솔루션이 있습니다. 간단히 대체 값을 제공하여 두 동작 사이를 전환할 수 있는 솔루션입니다.

 function getFields(list, field, otherwise) { // determine once whether or not to use the 'otherwise' var alt = typeof otherwise !== 'undefined'; // reduce the provided list to an array only containing the requested field return list.reduce(function(carry, item) { // If item is an object and contains the field, add its value and the value of 'otherwise' if it was provided if (typeof item === 'object' && field in item) { carry.push(item[field]); } else if (alt) { carry.push(otherwise); } // return the 'carry' (which is the list of matched field values) return carry; }, []); }

jsbin 예제

위의 예가 (잘하면) 이것이 작동하는 방식에 약간의 빛을 비춰 Array.concat 함수를 사용하여 함수를 약간 줄이겠습니다.

 function getFields(list, field, otherwise) { var alt = typeof otherwise !== 'undefined'; return list.reduce(function(carry, item) { return carry.concat(typeof item === 'object' && field in item ? item[field] : (alt ? otherwise : [])); }, []); }

jsbin 예제


Rogier Spieker

일반적으로 배열 내부에 있는 객체 값을 외삽하려면(질문에 설명된 것처럼) reduce, map 및 array destructuring을 사용할 수 있습니다.

ES6

 let a = [{ z: 'word', c: 'again', d: 'some' }, { u: '1', r: '2', i: '3' }]; let b = a.reduce((acc, obj) => [...acc, Object.values(obj).map(y => y)], []); console.log(b)

for in 루프를 사용하는 것과 동등한 것은 다음과 같습니다.

 for (let i in a) { let temp = []; for (let j in a[i]) { temp.push(a[i][j]); } array.push(temp); }

생성된 출력: ["단어", "다시", "일부", "1", "2", "3"]


Eugen Sunic

ES6+에서 여러 값을 원하면 다음이 작동합니다.

 objArray = [ { foo: 1, bar: 2, baz: 9}, { foo: 3, bar: 4, baz: 10}, { foo: 5, bar: 6, baz: 20} ]; let result = objArray.map(({ foo, baz }) => ({ foo, baz }))

이것은 왼쪽의 {foo, baz} 가 객체 소멸을 사용하고 화살표의 오른쪽 이 ES6의 향상된 객체 리터럴 로 인해 {foo: foo, baz: baz} 와 동일하게 작동합니다.


Chris Magnuson

배열과 유사한 객체도 지원하려면 Array.from (ES2015)을 사용하세요.

 Array.from(arrayLike, x => x.foo);

Array.prototype.map() 메서드에 비해 이점은 입력도 Set일 수 있다는 것입니다.

 let arrayLike = new Set([{foo: 1}, {foo: 2}, {foo: 3}]);

TechWisdom

중첩 배열이 있는 경우 다음과 같이 작동하도록 할 수 있습니다.

 const objArray = [ { id: 1, items: { foo:4, bar: 2}}, { id: 2, items: { foo:3, bar: 2}}, { id: 3, items: { foo:1, bar: 2}} ]; let result = objArray.map(({id, items: {foo}}) => ({id, foo})) console.log(result)


Qui-Gon Jinn

객체 배열에서 여러 속성을 쉽게 추출:

 let arrayOfObjects = [ {id:1, name:'one', desc:'something'}, {id:2, name:'two', desc:'something else'} ]; //below will extract just the id and name let result = arrayOfObjects.map(({id, name}) => ({id, name}));

result[{id:1, name:'one'},{id:2, name:'two'}]

지도 기능에서 필요에 따라 속성 추가 또는 제거


GavinBelson

그것은 "더 나은"의 정의에 따라 다릅니다.

다른 답변은 자연스럽고(특히 기능적 스타일에 익숙한 남성의 경우) 간결한 map의 사용을 지적합니다. 나는 그것을 사용하는 것을 강력히 추천한다(만약 당신이 몇몇 IE8-IT 사람들을 귀찮게 하지 않는다면). 따라서 "더 나은"이 "더 간결한", "유지 관리 가능한", "이해할 수 있는"을 의미한다면 예, 훨씬 더 좋습니다.

반면에 이 아름다움은 추가 비용 없이 얻을 수 없습니다. 나는 microbench의 열렬한 팬이 아니지만 여기에 작은 테스트를 해봤습니다 . 결과는 예측 가능하며 이전의 추악한 방법이 map 기능보다 빠른 것 같습니다. 따라서 "더 나은"이 "더 빠른"을 의미한다면 아니요, 구식 패션을 유지하십시오.

다시 말하지만 이것은 단지 마이크로벤치이며 map 의 사용을 옹호하는 것이 아닙니다. 단지 2센트입니다. :).


sitifensys

위의 답변은 단일 속성에 적합하지만 배열에서 여러 속성을 선택할 때 이것을 사용하십시오

 var arrayObj=[{Name,'A',Age:20,Email:'a.gmail.com'},{Name,'B',Age:30,Email:'b.gmail.com'},{Name,'C',Age:40,Email:'c.gmail.com'}]

이제 두 개의 필드만 선택합니다.

 var outPutArray=arrayObj.map(( {Name,Email} ) => ({Name,Email}) ) console.log(outPutArray)

Kamlesh Singh

위에 제공된 답변은 단일 속성 을 추출하는 데 좋습니다. 객체 배열에서 둘 이상의 속성을 추출하려면 어떻게 해야 할까요? 여기 해결책이 있습니다!! 그 경우 우리는 단순히 _.pick(object, [paths])를 사용할 수 있습니다

 _.pick(object, [paths])

objArray에 아래와 같은 세 가지 속성이 있는 객체가 있다고 가정해 보겠습니다.

 objArray = [ { foo: 1, bar: 2, car:10}, { foo: 3, bar: 4, car:10}, { foo: 5, bar: 6, car:10} ];

이제 모든 객체에서 foo 및 bar 속성을 추출하여 별도의 배열에 저장하려고 합니다. 먼저 map을 사용하여 배열 요소를 반복한 다음 Lodash Library Standard _.pick() 메서드를 적용합니다.

이제 'foo' 및 'bar' 속성을 추출할 수 있습니다.

var newArray = objArray.map((element)=>{ return _.pick(element, ['foo','bar'])}) console.log(newArray);

결과는 [{foo: 1, bar: 2},{foo: 3, bar: 4},{foo: 5, bar: 6}]입니다.

즐겨!!!


Akash Jain

ES6에서 필드를 문자열로 동적으로 전달하려는 경우:

 function getFields(array, field) { return array.map(a => a[field]); } let result = getFields(array, 'foo');

Kurt Van den Branden

함수 맵은 객체 배열을 다룰 때 좋은 선택입니다. 이미 좋은 답변이 많이 게시되어 있지만 지도와 필터를 조합하여 사용하는 예가 도움이 될 수 있습니다.

값이 정의되지 않은 속성을 제외하거나 특정 속성만 제외하려는 경우 다음을 수행할 수 있습니다.

 var obj = {value1: "val1", value2: "val2", Ndb_No: "testing", myVal: undefined}; var keysFiltered = Object.keys(obj).filter(function(item){return !(item == "Ndb_No" || obj[item] == undefined)}); var valuesFiltered = keysFiltered.map(function(item) {return obj[item]});

https://jsfiddle.net/ohea7mgk/


Niko Gamulin

빈 배열을 만든 다음 목록에서 forEach 요소를 만들고 해당 개체에서 원하는 것을 빈 배열로 푸시합니다.

 let objArray2 = []; objArray.forEach(arr => objArray2.push(arr.foo));

Qiimiia

map() 메서드는 호출 배열의 모든 요소에 대해 제공된 함수를 호출한 결과로 채워진 새 배열을 만듭니다.

 let kvArray = [{key: 1, value: 10}, {key: 2, value: 20}, {key: 3, value: 30}] let reformattedArray = kvArray.map(obj => { return obj.value })

또는

 const kvArray = [['key1', 'value1'], ['key2', 'value2']] // Use the regular Map constructor to transform a 2D key-value Array into a map const myMap = new Map(kvArray) myMap.get('key1') // returns "value1" // Use Array.from() to transform a map into a 2D key-value Array console.log(Array.from(myMap)) // Will show you exactly the same Array as kvArray // A succinct way to do the same, using the spread syntax console.log([...myMap]) // Or use the keys() or values() iterators, and convert them to an array console.log(Array.from(myMap.keys())) // ["key1", "key2"]

MD SHAYON

출처 : http:www.stackoverflow.com/questions/19590865/from-an-array-of-objects-extract-value-of-a-property-as-array

반응형