JavaScript로 객체 배열에서 고유 한 값을 얻는 방법은 무엇입니까?


383

다음이 있다고 가정합니다.

var array = 
    [
        {"name":"Joe", "age":17}, 
        {"name":"Bob", "age":17}, 
        {"name":"Carl", "age": 35}
    ]

결과 배열을 얻을 수 있도록 모든 연령대를 배열 할 수있는 가장 좋은 방법은 무엇입니까?

[17, 35]

대안으로 데이터 또는 더 나은 방법을 구성하여 "age"의 값을 확인하고 각 배열의 존재 여부를 확인하고 그렇지 않은 경우 추가 할 수 있도록 각 배열을 반복 할 필요가없는 방법이 있습니까?

어떤 방법이 있다면 반복하지 않고 독특한 연령대를 끌어낼 수 있습니다 ...

현재 비효율적 인 방법으로 개선하고 싶습니다 ... "어레이"대신 객체의 배열이지만 일부 고유 키 (예 : "1,2,3")가있는 객체의 "맵"인 경우 그래요 가장 효율적인 방법을 찾고 있습니다.

다음은 현재 내가하는 방법이지만, 반복 작업은 효과가 있지만 효율성이 크지 않은 것처럼 보입니다 ...

var distinct = []
for (var i = 0; i < array.length; i++)
   if (array[i].age not in distinct)
      distinct.push(array[i].age)

34
반복은 "효율을 위해 혼란스럽지"않으며 "반복없이"모든 요소에 대해 아무것도 할 수 없습니다. 기능적으로 보이는 다양한 방법을 사용할 수 있지만 궁극적으로 일정 수준의 항목이 항목을 반복해야합니다.
Eevee February

// 100 % 실행 코드 const listOfTags = [{id : 1, 레이블 : "Hello", 색상 : "red", 정렬 : 0}, {id : 2, 레이블 : "World", 색상 : "green", 정렬 : 1}, {id : 3, 레이블 : "Hello", 색상 : "blue", 정렬 : 4}, {id : 4, 레이블 : "Sunshine", 색상 : "yellow", 정렬 : 5}, {id : 5, 레이블 : "Hello", 색상 : "red", 정렬 : 6}], 키 = [ 'label', 'color'], 필터링 됨 = listOfTags.filter ((s => o => (k => ! s.has (k) && s.add (k)) (keys.map (k => o [k]). join ( '|'))) (새 세트)); console.log (필터링);
Sandeep Mishra

1
현상금은 매우 중요하지만, 주어진 데이터 환불 문제는 이미 여기에 대한 답변 : stackoverflow.com/questions/53542882/...를 . 현상금의 목적은 무엇입니까? 두 개 이상의 키로이 특정 문제에 대답해야합니까?
Nina Scholz '08

Set물건과 map낭비입니다. 이 작업은 간단한 .reduce()단계를 수행합니다.
Redu

답변:


126

이것이 PHP라면 키로 배열을 만들고 array_keys마지막에 가져갈 것이지만 JS에는 그런 사치가 없습니다. 대신 이것을 시도하십시오 :

var flags = [], output = [], l = array.length, i;
for( i=0; i<l; i++) {
    if( flags[array[i].age]) continue;
    flags[array[i].age] = true;
    output.push(array[i].age);
}

15
아니요, array_unique여기에 요청 된 연령뿐만 아니라 전체 항목을 비교 하기 때문 입니다.
Niet the Dark Absol

6
나는 생각 flags = {}보다 더 낫다flags = []
zhuguowei

3
@zhuguowei는 아마도 희소 배열에는 아무런 문제가 없지만 아마도 age작은 정수 라고 가정합니다 (<120).
Niet the Dark Absol

나이가 같은 사람들의 총수를 어떻게 인쇄 할 수 있을까요?
user1788736

605

ES6 / ES2015 이상을 사용하는 경우 다음과 같이 할 수 있습니다.

const unique = [...new Set(array.map(item => item.age))];

방법은 다음과 같습니다 .


11
오류가 발생했습니다 :TypeError: (intermediate value).slice is not a function
Github의 AngJobs

7
@Thomas ...는 스프레드 연산자를 의미합니다. 이 경우 새 세트를 만들어 목록에 펼칩니다. 자세한 내용은 여기를 참조하십시오. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Vlad Bezden

10
typescript의 경우 Array.from ()에 싸인 새로운 Set을 사용해야합니다 ... 아래에 그 대답을 제공 할 것입니다. @AngJobs
기독교 매튜

4
객체의 여러 키를 기반으로 고유 한 객체를 찾을 수 있습니까?
Jefree Sujit

13
이 솔루션은 몇 달 전에 @Russell Vea에 의해 거의 그대로 사용 되었습니다. 기존 답변을 확인 했습니까? 그러나 다시 한 번, 266+ 이상의 투표는 아무도 확인하지 않은 것으로 나타났습니다.
Dan Dascalescu

164

ES6 사용

let array = [
  { "name": "Joe", "age": 17 },
  { "name": "Bob", "age": 17 },
  { "name": "Carl", "age": 35 }
];
array.map(item => item.age)
  .filter((value, index, self) => self.indexOf(value) === index)

> [17, 35]

2
인덱스로 값을 얻으려면 어떻게 얻을 수 있습니까? 예 : { "name": "Bob", "age": "17"}, { "name": "Bob", "age ":"17 "}
Abdullah Al Mamun

10
당신이 스크롤을 유지하는 이유의
알레한드로 Bastidas

5
@AbdullahAlMamun 먼저 다음과 같이 .map을 호출하는 대신 .filter에서 map을 사용할 수 있습니다.array.filter((value, index, self) => self.map(x => x.age).indexOf(value.age) == index)
Leo

1
ps : .filter 안의 .map이 느릴 수 있으므로 큰 배열에주의하십시오
Leo

2
@IvanNosov 스 니펫은 매우 유용하지만,지도를 작성하고 문서를 필터링하는 포인터로 작동하는 방법에 대한 몇 줄의 설명은 초보자에게 완벽하고 명확합니다.
azakgaim

128

이와 같은 사전 접근 방식을 사용할 수 있습니다. 기본적으로 "사전"에서 키로 구별 할 값을 지정합니다 (여기서는 사전 모드를 피하기 위해 배열을 객체로 사용합니다). 키가 존재하지 않으면 해당 값을 고유 한 값으로 추가하십시오.

작동하는 데모는 다음과 같습니다.

var array = [{"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}];
var unique = [];
var distinct = [];
for( let i = 0; i < array.length; i++ ){
  if( !unique[array[i].age]){
    distinct.push(array[i].age);
    unique[array[i].age] = 1;
  }
}
var d = document.getElementById("d");
d.innerHTML = "" + distinct;
<div id="d"></div>

이것은 O (n)입니다. 여기서 n은 배열의 객체 수이고 m은 고유 값의 수입니다. 각 값을 한 번 이상 검사해야하므로 O (n)보다 빠른 방법은 없습니다.

이것의 이전 버전은 객체를 사용했고 안으로 들어 왔습니다. 이것들은 본질적으로 사소한 것이었고, 이후에 약간 업데이트되었습니다. 그러나 원래 jsperf에서 두 버전간에 성능이 향상되는 이유는 데이터 샘플 크기가 너무 작기 때문입니다. 따라서 이전 버전의 주요 비교는 내부 맵과 필터 사용과 사전 모드 조회의 차이점을 살펴 보는 것입니다.

위에서 언급했듯이 위의 코드를 업데이트했지만 3 대신 1000 개의 객체를 살펴보기 위해 jsperf도 업데이트했습니다. 3 관련된 많은 성능 함정을 간과 했습니다. ).

공연

https://jsperf.com/filter-vs-dictionary-more-data 이 사전을 실행할 때 96 % 더 빨랐습니다.

필터 대 사전


4
추가 플러그인없이 빠르고 빠릅니다. 정말 멋지다
mihai

2
어떻 if( typeof(unique[array[i].age]) == "undefined"){ distinct.push(array[i].age); unique[array[i].age] = 0; }
Timeless

7
와우 성능이지도 옵션에 유리하게 바뀌 었습니다. 그 jsperf 링크를 클릭하십시오!
AT

1
@ 98percentmonkey-개체는 "사전 접근"을 용이하게하기 위해 사용되었습니다. 개체 내부에서 추적중인 각 항목이 키 (또는 저장소)로 추가됩니다. 이런 식으로 발생을 발견하면 키 (또는 빈)가 있는지 확인할 수 있습니다. 존재하는 경우, 발생이 고유하지 않다는 것을 알고 있습니다. 존재하지 않는 경우 발생이 고유하다는 것을 알고 추가합니다.
Travis J

1
@ 98percentmonkey-객체를 사용하는 이유는 조회가 속성 이름을 한 번 확인하기 때문에 O (1)이고, 배열은 존재를 확인하기 위해 모든 값을 봐야하기 때문에 O (n)이기 때문입니다. 프로세스가 끝날 때 객체의 키 세트 (빈)는 고유 한 발생 세트를 나타냅니다.
트래비스 J

91

2017 년 8 월 25 일 현재 Typescript 용 ES6를 통한 새로운 세트를 사용하여이 문제를 해결하는 방법입니다.

Array.from(new Set(yourArray.map((item: any) => item.id)))

3
이것은 도움이되었고, 전에 감사를 얻었습니다. 유형 'Set'은 배열 유형이 아닙니다.
robert king

1
이것은 좋은 대답입니다. 내가 이것을 아래로 스크롤 할 때까지 Object.keys (values.reduce <any> ((x, y) => {x [y] = null; return x;}, {} )); 그러나이 대답은보다 간결하며 문자열 대신 모든 데이터 유형에 적용됩니다.
jgosar

1
이 답변은 훌륭합니다!
lukeocodes

78

ES6 기능을 사용하면 다음과 같은 작업을 수행 할 수 있습니다.

const uniqueAges = [...new Set( array.map(obj => obj.age)) ];

6
이 접근법은 기본 유형 (연령이 숫자 배열이므로 여기에서만 해당)에서만 작동하지만 객체에는 실패합니다.
k0pernikus 2016 년

두 개의 키가있는 객체에 어떻게 작동시키는 지 알고 있습니까?
cegprakash

1
뭔가 같은const uniqueObjects = [ ...new Set( array.map( obj => obj.age) ) ].map( age=> { return array.find(obj => obj.age === age) } )
할리 B

62

Dups를 매핑하고 제거합니다.

var ages = array.map(function(obj) { return obj.age; });
ages = ages.filter(function(v,i) { return ages.indexOf(v) == i; });

console.log(ages); //=> [17, 35]

편집 : Aight! 성능면에서 가장 효율적인 방법은 아니지만 가장 읽기 쉬운 IMO입니다. 마이크로 최적화에 관심이 있거나 엄청난 양의 데이터가 있다면 규칙적인 for루프가 더 "효율적"입니다.


3
@elclanrs- "가장 효율적인 성능"-이 방법은 느립니다 .
트래비스 J

1
@Eevee : 알겠습니다. 답의 밑줄 버전도 매우 빠르지 않습니다 . 결국 더 편리한 것을 선택하면 일반 테스트에서 1-30 % 정도가 "거대한 개선"을 반영하고 OP /가 수천에있을 때 의심합니다. .
elclanrs 2013

4
물론 이죠 세 개의 요소 만 있으면 가장 빠른 것은 세 개의 변수를 만들고 일부를 사용하는 것 if입니다. 3 백만으로 매우 다른 결과를 얻을 수 있습니다.
Eevee February

1
빠르지는 않지만 내 경우에는 큰 데이터 세트를 처리하지 않으므로 트릭을 수행했습니다. 감사합니다.
Felipe Alarcon

37
var unique = array
    .map(p => p.age)
    .filter((age, index, arr) => arr.indexOf(age) == index)
    .sort(); // sorting is optional

// or in ES6

var unique = [...new Set(array.map(p => p.age))];

// or with lodash

var unique = _.uniq(_.map(array, 'age'));

ES6 예

const data = [
  { name: "Joe", age: 17}, 
  { name: "Bob", age: 17}, 
  { name: "Carl", age: 35}
];

const arr = data.map(p => p.age); // [17, 17, 35]
const s = new Set(arr); // {17, 35} a set removes duplications, but it's still a set
const unique = [...s]; // [17, 35] Use the spread operator to transform a set into an Array
// or use Array.from to transform a set into an array
const unique2 = Array.from(s); // [17, 35]

6
이 코드는 질문에 대답 할 수 있지만 문제를 해결하는 방법이유 에 대한 추가 컨텍스트를 제공 하면 답변의 장기적인 가치가 향상됩니다.
Alexander

indexOf와 인덱스를 사용하는 첫 번째 것은 훌륭합니다.
아아

이것은 프리미티브 값에만 적용됩니다. 날짜 배열이 있으면 좀 더 사용자 정의 된 방법이 필요합니다. 여기에서 더 읽으십시오 : codeburst.io/javascript-array-distinct-5edc93501dc4
Molx

36

키로 고유 한 모든 속성을 가진 객체반환 하려는 경우

const array =
  [
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
  ]

const key = 'age';

const arrayUniqueByKey = [...new Map(array.map(item =>
  [item[key], item])).values()];

console.log(arrayUniqueByKey);

   /*OUTPUT
       [
        { "name": "Bob", "age": 17 },
        { "name": "Carl", "age": 35 }
       ]
   */

 // Note: this will pick the last duplicated item in the list.


2
참고 : 목록에서 마지막으로 복제 된 항목을 선택합니다.
유진 쿨라 부 호프

1
이것을 답변에 추가하십시오!
Arun Kumar Saini

1
정확히 내가 찾던 것. 공유 주셔서 감사합니다!
Devner

1
나는 이것이 정직한 TOP 대답이어야한다고 생각합니다!
Jaroslav Benc

26

이미 유효한 답변이 많이 있지만 reduce()깨끗하고 단순하기 때문에 메소드 만 사용하는 답변을 추가하고 싶었습니다 .

function uniqueBy(arr, prop){
  return arr.reduce((a, d) => {
    if (!a.includes(d[prop])) { a.push(d[prop]); }
    return a;
  }, []);
}

다음과 같이 사용하십시오.

var array = [
  {"name": "Joe", "age": 17}, 
  {"name": "Bob", "age": 17}, 
  {"name": "Carl", "age": 35}
];

var ages = uniqueBy(array, "age");
console.log(ages); // [17, 35]

20

forEach(최신 브라우저 및 노드 JS 세계에 도움) @ 트래비스-J의 답변 버전 :

var unique = {};
var distinct = [];
array.forEach(function (x) {
  if (!unique[x.age]) {
    distinct.push(x.age);
    unique[x.age] = true;
  }
});

Chrome v29.0.1547에서 34 % 빨라짐 : http://jsperf.com/filter-versus-dictionary/3

그리고 매퍼 기능을 사용하는 일반적인 솔루션 (직접 맵보다 느리지 만 예상되는 결과) :

function uniqueBy(arr, fn) {
  var unique = {};
  var distinct = [];
  arr.forEach(function (x) {
    var key = fn(x);
    if (!unique[key]) {
      distinct.push(key);
      unique[key] = true;
    }
  });
  return distinct;
}

// usage
uniqueBy(array, function(x){return x.age;}); // outputs [17, 35]

1
나이가 실제 시나리오에서 필요한 유일한 가치는 아닐 것이므로 일반적인 솔루션을 가장 좋아합니다.
토 프트

5
일반적으로 "distinct.push (key)"를 "distinct.push (x)"로 변경하면 실제로 사용할 수있는 실제 요소 목록이 반환됩니다.
Silas Hansen

15

기본적으로 모든 새 프로젝트에서 Underscore 를 고수하기 시작 했기 때문에 이러한 작은 데이터 전송 문제에 대해 생각할 필요가 없습니다.

var array = [{"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}];
console.log(_.chain(array).map(function(item) { return item.age }).uniq().value());

생산 [17, 35]합니다.


13

이 문제를 해결하는 또 다른 방법이 있습니다.

var result = {};
for(var i in array) {
    result[array[i].age] = null;
}
result = Object.keys(result);

이 솔루션이 다른 솔루션과 비교하여 얼마나 빠른지 모르겠지만 더 깨끗한 모양을 좋아합니다. ;-)


편집 : 좋아, 위의 모든 것 중에서 가장 느린 해결책 인 것 같습니다.

여기에 성능 테스트 사례를 만들었습니다. http://jsperf.com/distinct-values-from-array

연령 (정수)을 테스트하는 대신 이름 (문자열)을 비교하기로했습니다.

방법 1 (TS의 솔루션)은 매우 빠릅니다. 흥미롭게도 Method 7은 다른 모든 솔루션보다 뛰어납니다. 여기서는 .indexOf ()를 제거하고 루프 된 함수 호출을 피하면서 "수동"구현을 사용했습니다.

var result = [];
loop1: for (var i = 0; i < array.length; i++) {
    var name = array[i].name;
    for (var i2 = 0; i2 < result.length; i2++) {
        if (result[i2] == name) {
            continue loop1;
        }
    }
    result.push(name);
}

Safari와 Firefox를 사용하는 성능의 차이는 놀랍습니다. 그리고 Chrome이 최적화에서 최고의 역할을하는 것처럼 보입니다.

왜 위의 스 니펫이 다른 코드와 비교하여 그렇게 빠른지 잘 모르겠습니다. 어쩌면 나보다 현명한 사람이 대답 할 수 있습니다. ;-)


9

lodash를 사용하여

var array = [
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
];
_.chain(array).pluck('age').unique().value();
> [17, 35]

2
질문에 암시 된 것처럼 일반 자바 스크립트로이를 수행하는 방법을 설명 할 수 있습니까?
Ruskin

밑줄 함수입니다. _.chain
vini

2
그러나 pluck ()은 lodash에 없습니다.
Yash Vekaria

1
_.chain (array) .map ( 'age'). unique (). value (); 나를 위해 일했다.
Yash Vekaria

버전 4.0에는 몇 가지 주요 변경 사항이 있습니다.- stackoverflow.com
a/31740263/4050261

7

Lodash 사용

var array = [
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
];

_.chain(array).map('age').unique().value();

반환 [17,35]


6
function get_unique_values_from_array_object(array,property){
    var unique = {};
    var distinct = [];
    for( var i in array ){
       if( typeof(unique[array[i][property]]) == "undefined"){
          distinct.push(array[i]);
       }
       unique[array[i][property]] = 0;
    }
    return distinct;
}


5

다음은 reduce를 사용하고 매핑을 허용하며 삽입 순서를 유지하는 다목적 솔루션입니다.

아이템 : 배열

mapper : 항목을 기준에 매핑하거나 비워 두어 항목 자체를 매핑하는 단항 함수입니다.

function distinct(items, mapper) {
    if (!mapper) mapper = (item)=>item;
    return items.map(mapper).reduce((acc, item) => {
        if (acc.indexOf(item) === -1) acc.push(item);
        return acc;
    }, []);
}

용법

const distinctLastNames = distinct(items, (item)=>item.lastName);
const distinctItems = distinct(items);

이것을 배열 프로토 타입에 추가하고 스타일 인 경우 items 매개 변수를 생략 할 수 있습니다.

const distinctLastNames = items.distinct( (item)=>item.lastName) ) ;
const distinctItems = items.distinct() ;

배열 대신 Set을 사용하여 일치 속도를 높일 수도 있습니다.

function distinct(items, mapper) {
    if (!mapper) mapper = (item)=>item;
    return items.map(mapper).reduce((acc, item) => {
        acc.add(item);
        return acc;
    }, new Set());
}

5

const x = [
  {"id":"93","name":"CVAM_NGP_KW"},
  {"id":"94","name":"CVAM_NGP_PB"},
  {"id":"93","name":"CVAM_NGP_KW"},
  {"id":"94","name":"CVAM_NGP_PB"}
].reduce(
  (accumulator, current) => accumulator.some(x => x.id === current.id)? accumulator: [...accumulator, current ], []
)

console.log(x)

/* output 
[ 
  { id: '93', name: 'CVAM_NGP_KW' },
  { id: '94', name: 'CVAM_NGP_PB' } 
]
*/


2
이것은 O (n ^ 2)처럼 보입니다
cegprakash

4

방금 이것을 찾았고 유용하다고 생각했습니다.

_.map(_.indexBy(records, '_id'), function(obj){return obj})

밑줄을 다시 사용 하므로 이와 같은 객체가 있으면

var records = [{_id:1,name:'one', _id:2,name:'two', _id:1,name:'one'}]

그것은 당신에게 유일한 객체를 줄 것입니다.

여기서 일어나는 일은 이런 indexBy맵 을 반환하는 것입니다

{ 1:{_id:1,name:'one'}, 2:{_id:2,name:'two'} }

지도이기 때문에 모든 키가 고유합니다.

그런 다음이 목록을 배열에 다시 매핑합니다.

고유 한 값만 필요한 경우

_.map(_.indexBy(records, '_id'), function(obj,key){return key})

(가) 있다는 사실을 숙지 key대신 정수를 필요로하는 경우, 당신이해야하므로 문자열로 반환

_.map(_.indexBy(records, '_id'), function(obj,key){return parseInt(key)})

4

groupBy 기능을 찾고 있다고 생각합니다 (Lodash 사용).

_personsList = [{"name":"Joe", "age":17}, 
                {"name":"Bob", "age":17}, 
                {"name":"Carl", "age": 35}];
_uniqAgeList = _.groupBy(_personsList,"age");
_uniqAges = Object.keys(_uniqAgeList);

결과를 생성합니다 :

17,35

jsFiddle 데모 : http://jsfiddle.net/4J2SX/201/


3

나와 같은 속도를 유지하면서보다 "기능적인"기능을 선호하는 경우이 예에서는 축소 클로저 안에 래핑 된 빠른 사전 검색을 사용합니다.

var array = 
[
    {"name":"Joe", "age":17}, 
    {"name":"Bob", "age":17}, 
    {"name":"Carl", "age": 35}
]
var uniqueAges = array.reduce((p,c,i,a) => {
    if(!p[0][c.age]) {
        p[1].push(p[0][c.age] = c.age);
    }
    if(i<a.length-1) {
        return p
    } else {
        return p[1]
    }
}, [{},[]])

테스트 에 따르면 내 솔루션은 제안 된 답변보다 두 배 빠릅니다.


3
[...new Set([
    { "name": "Joe", "age": 17 },
    { "name": "Bob", "age": 17 },
    { "name": "Carl", "age": 35 }
  ].map(({ age }) => age))]

3

내 코드는 길이가 짧고 시간이 복잡하지 않다는 것을 알고 있지만 이해할 수 있으므로이 방법을 시도했습니다.

프로토 타입 기반 함수를 개발하려고하는데 코드도 변경됩니다.

여기, Distinct는 제 고유의 프로토 타입 기능입니다.

<script>
  var array = [{
      "name": "Joe",
      "age": 17
    },
    {
      "name": "Bob",
      "age": 17
    },
    {
      "name": "Carl",
      "age": 35
    }
  ]

  Array.prototype.Distinct = () => {
    var output = [];
    for (let i = 0; i < array.length; i++) {
      let flag = true;
      for (let j = 0; j < output.length; j++) {
        if (array[i].age == output[j]) {
          flag = false;
          break;
        }
      }
      if (flag)
        output.push(array[i].age);
    }
    return output;
  }
  //Distinct is my own function
  console.log(array.Distinct());
</script>


2

Array.prototype.includes가 포함되어 있거나 polyfill 하려는 경우 다음 과 같이 작동합니다.

var ages = []; array.forEach(function(x) { if (!ages.includes(x.age)) ages.push(x.age); });

1

아래 코드는 나이가 고유하지 않은 새로운 배열뿐만 아니라 나이가 중복되지 않는 새로운 배열을 보여줍니다.

var data = [
  {"name": "Joe", "age": 17}, 
  {"name": "Bob", "age": 17}, 
  {"name": "Carl", "age": 35}
];

var unique = [];
var tempArr = [];
data.forEach((value, index) => {
    if (unique.indexOf(value.age) === -1) {
        unique.push(value.age);
    } else {
        tempArr.push(index);    
    }
});
tempArr.reverse();
tempArr.forEach(ele => {
    data.splice(ele, 1);
});
console.log('Unique Ages', unique);
console.log('Unique Array', data);```

1

나는 Kotlin에서와 같은 일반적인 경우를 위해 TypeScript에서 내 자신을 썼습니다 Array.distinctBy {}...

function distinctBy<T, U extends string | number>(array: T[], mapFn: (el: T) => U) {
  const uniqueKeys = new Set(array.map(mapFn));
  return array.filter((el) => uniqueKeys.has(mapFn(el)));
}

U물론 해시 가능한 곳 은 어디 입니까? 객체의 경우 https://www.npmjs.com/package/es6-json-stable-stringify 가 필요할 수 있습니다.


1

전체 객체의 고유 한 것이 필요한 경우

const _ = require('lodash');

var objects = [
  { 'x': 1, 'y': 2 },
  { 'y': 1, 'x': 2 },
  { 'x': 2, 'y': 1 },
  { 'x': 1, 'y': 2 }
];

_.uniqWith(objects, _.isEqual);

[개체 {x : 1, y : 2}, 개체 {x : 2, y : 1}]


downvoter : 왜 downvote를 설명 하는가?
cegprakash '11

1

이 오래된 질문에 대답하는 것은 의미가 없지만 Javascript의 본질을 나타내는 간단한 대답이 있습니다. Javascript의 객체는 본질적으로 해시 테이블입니다. 이것을 사용하여 고유 키의 해시를 얻을 수 있습니다.

var o = {}; array.map(function(v){ o[v.age] = 1; });

그런 다음 해시를 고유 한 값의 배열로 줄일 수 있습니다.

var a2 = []; for (k in o){ a2.push(k); }

그게 당신이 필요한 전부입니다. 배열 a2 에는 고유 한 연령대 만 포함됩니다.


1

뛰어난 성능의 단순한 원 라이너. 내 테스트 에서 ES6 솔루션보다 6 % 빠릅니다 .

var ages = array.map(function(o){return o.age}).filter(function(v,i,a) {
    return a.indexOf(v)===i
});

@ Jeb50 읽기 쉬운 여러 줄을 추가해야합니까? 여기에있는 다른 것들을 보면 나는 그들이 읽거나 이해하기 쉽다고 느끼지 않습니다. 나는 그것이하는 일을 설명하는 함수에 이것을 배치하는 것이 가장 좋다고 생각합니다.
크레이그

2
화살표 기능 포함 : array.map( o => o.age).filter( (v,i,a) => a.indexOf(v)===i). 함수 키워드를 거의 사용하지 않아서 볼 때 내용을 두 번 읽어야합니다 😊
Drenai
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.