배열에서 중복 제거


100

다음과 같은 개체 배열이 있습니다.

var array = [
    {id:123, value:"value1", name:"Name1"},
    {id:124, value:"value2", name:"Name1"},
    {id:125, value:"value3", name:"Name2"},
    {id:126, value:"value4", name:"Name2"}
    ...
];

보시다시피 일부 이름은 반복됩니다. 이름 만있는 새 배열을 얻고 싶지만 일부 이름이 반복되면 다시 추가하고 싶지 않습니다. 이 배열을 원합니다.

var newArray = ["Name1", "Name2"];

나는 이것을 시도하고있다 map:

var newArray = array.map((a) => {
    return a.name;
});

그러나 문제는 이것이 반환된다는 것입니다.

newArray = ["Name1", "Name1", "Name2", "Name2"];

내부 map에 조건을 설정 하여 이미 존재하는 요소를 반환하지 않도록하려면 어떻게해야합니까? 이 작업을 map다른 ECMAScript 5 또는 ECMAScript 6 기능 으로 수행하고 싶습니다 .


2
그런 다음 어레이에서 중복을 제거하십시오.
— Tushar



id : 125가 포함 된 줄이 쉼표로 끝나지 않는 이유는 무엇입니까?
— Peter Mortensen

.indexOf ()를 사용하는 모든 답변 은 2 차 시간 복잡성 으로 인해 배열이 크면 성능 이 저하됩니다 . ES6 세트를 사용하거나 ES5 객체 를 사전으로 사용하는 것이 좋습니다 .
— joeytwiddle

답변:


210

ES6를 사용 Set하면 개체의 이름 만 매핑 한 후 고유 한 값을 사용할 수 있습니다 .

이 제안은 새 배열에서 항목을 수집하기 위해 스프레드 구문... 을 사용합니다 .

const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }],
      names = [...new Set(array.map(a => a.name))];

console.log(names);


9
내 정보를 위해 .. 무엇을 ...합니까?
— Rajshekar Reddy

9
@RajshekarReddy, 반복 가능한 객체로 배열을 구축하기위한 확산 구문... 입니다.
— Nina Scholz

5
나는 "Set"자체에 대해 찬성하는 것이 아니라 스프레드 연산자의 현명한 사용을 위해 찬성하는 것입니다. 새로운 것을 배우거나 실제 사례에 적용된 새로운 것을 보는 것은 항상 좋은 일이므로이 게시물은 찬성 할 가치가 있습니다.
— briosheje

33
그것은 내 개인적인 의견이지만 다소 일반적인 의견 입니다. 사용 Array.from은 변환의 의도를 훨씬 더 잘 전달하고 (또한 초보자를위한 이해 / 검색이 더 쉬움), 확산 구문은 확산 된 요소가 여러 요소 중 하나 인 경우에만 사용해야합니다. 아마도 그것을 "나쁜 관행"이라고 부르는 것은 너무 가혹합니다. 미안합니다. 단지 그것이 일반적인 관용구가되는 것을 막고 싶습니다.
— Bergi

3
@KRyan은 ES6가 그렇게 새롭습니까? 2015 년 6 월에 마무리되었습니다. 그것은의 시간이 새로운 기능을 이해하고 사용하려면
— edc65

64

ES 6 (Set 없음)이 아닌 JavaScript 솔루션을 찾고 있다면 Array의 reduce방법을 사용할 수 있습니다 .

var array=[
  {id:123, value:"value1", name:"Name1"},
  {id:124, value:"value2", name:"Name1"},
  {id:125, value:"value3", name:"Name2"},
  {id:126, value:"value4", name:"Name2"}
];
var names = array.reduce(function (a, b) {
  if (a.indexOf(b.name) == -1) {
    a.push(b.name)
  }
  return a;
}, []);

console.log(names);


2
이 답변은 또한 중간 배열이나 집합, 특히 이름 자체 만 포함하는 집합이 필요하지 않다는 이점이 있습니다. (객체 배열에서 객체 배열로 직접 이동합니다.) +1
— jpmc26

@Iwrestledabearonce,이 두 번째 매개 변수는 반환 된 매개 변수와 동일한 객체가 아닙니까?
— Kaiido

네,하지만 정렬이나 필터처럼 하나에서 다른 곳으로 곧바로 가지 않습니다. 빈 배열에서 다시 만들어졌습니다.
— 곰과 레슬링 한 적이 있습니다.

1
@Dekel - 작은 버전 :var names = array.reduce(function(a, b) { a.indexOf(b.name) === -1 && a.push(b.name) return a; }, []);
— 레이온

3
@Rayon 소스 코드의 크기에 너무 많은 관심을 기울이지 마십시오. 이것은 많은 자작 프로그래머에게 일반적인 함정이며 가장 중요한 것은 프로그램이 효율적이고 읽기 쉬워야한다는 것입니다.
— leaf

16

개인적으로 모든 사람들이 ES 6을 좋아하는 이유를 모르겠습니다. 이것이 제 코드라면 가능한 한 많은 브라우저를 지원하고 싶습니다.

var array=[
{id:123, value:"value1", name:"Name1"},
{id:124, value:"value2", name:"Name1"},
{id:125, value:"value3", name:"Name2"},
{id:126, value:"value4", name:"Name2"}
];

   // Create array of unique names
var a = (function(a){
  for (var i = array.length; i--;)
    if (a.indexOf(array[i].name) < 0) a.push(array[i].name);
  return a;
})([]);

console.log(a);


2
indexOf항상 -ing 대신 객체를 사전으로 사용하는 것이 더 성능이 좋지 않을까요? 예 : do added[name] = trueand if(added[name])대신 if(a.indexOf(name)).
— Bojidar Marinov

7
"개인적으로 나는 왜 모든 사람들이 es6로 모든 것을 좋아하는지 알지 못합니다."왜 당신은를 구하고 goto fail, 색인 변수를 둘러싸는 범위로 유출하고 있는지 등. 이전 브라우저를 위해 폴리 필 / 변환하기 쉬운 부분입니다.
— 자레드 스미스

5
더 읽기 쉬운가요? 항목을 배열로 푸시하는 그것의 이상한 for 루프입니다. 훨씬 더 읽기보다 얻을 나던 ...
— 나는 곰을 한 번 씨름.

4
솔직히 말해서 불평 할 무언가를 찾기 위해 너무 열심히 노력하는 것 같습니다.
— 곰과 레슬링 한 적이 있습니다.

2
"저는 유명한 Apple SSL 버그를 언급하고 있습니다."-당신이 그냥 가서 문맥을 벗어난 임의의 주석으로 언급하고 사람들이 그것을 인식 할 것이라고 기대할 수 있다는 것은 그렇게 유명하지 않습니다.
— Hejazzman

14

또한 단순히 결합 수 map와filter

var array = [
  {id:123, value:"value1", name:"Name1"},
  {id:124, value:"value2", name:"Name1"},
  {id:125, value:"value3", name:"Name2"},
  {id:126, value:"value4", name:"Name2"}
];

var unique = array
  .map( item => item.name )
  .filter( ( item, idx, arr ) => arr.indexOf( item ) == idx ) 

console.log(unique)


11

Object.keys () 를 사용 하여 키가 파괴 된 이름 인 Array.prototype.reduce () 를 사용하여 반복 array변수 의 객체 결과에서 주어진 객체의 고유 한 열거 가능한 속성 이름의 배열을 가져올 수 있습니다.

암호:

const array = [{id:123, value:"value1", name:"Name1"}, {id:124, value:"value2", name:"Name1"}, {id:125, value:"value3", name:"Name2"}, {id:126, value:"value4", name:"Name2"}],
      names = Object.keys(array.reduce((a, { name }) => (a[name] = 1, a), {}))

console.log(names)


7

여기에 많은 좋은 답변이 있습니다. 저는 여러분에게 또 다른 관점을주기를 희망하면서 다양성을 가지고 기여하고 싶습니다.

배열은 JavaScript에서 객체 유형이므로 동시에 해시로 사용할 수 있습니다. 이 기능을 사용하면 O (n) 시간 복잡성으로 단일 감소 작업으로 수행 할 작업을 크게 단순화 할 수 있습니다.

배열 키 이외의 일부 속성을 보유하는 배열이 마음에 들지 않으면 별도의 해시 객체를 유지하는 것도 고려할 수 있습니다.

var array = [{id:123, value:"value1", name:"Name1"},
             {id:124, value:"value2", name:"Name1"},
             {id:125, value:"value3", name:"Name2"},
             {id:126, value:"value4", name:"Name2"}
            ],
result = array.reduce((p,c) => p[c.name] ? p : (p[c.name] = true, p.push(c.name), p), []);
console.log(result);


이 ES5 솔루션은 성능이 좋지만 두 가지 목적으로 어레이를 사용하는 것은 혼란스럽고 이름 중 하나가 숫자 일 경우 위험합니다. p[c.name]별도의 개체에서 작업을 수행 o한 다음 나중에 폐기 하는 것이 좋습니다 .
— joeytwiddle

7

name값만 필요하다면 a Set가 갈 길이 라는 데 동의합니다 .

그러나name 속성을 기반으로 고유 한 개체의 배열을 얻으려면 Map. 맵을 만드는 빠른 방법은 [key, value]배열 배열을 사용하는 것입니다.

const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }],
      unique = new Map(array.map(obj => [obj.name, obj]));

// To get the unique objects
const uniques = Array.from(unique.values());

// Get the names like you already did:
console.log("Names:", uniques.map(obj => obj.name));

// If you ever need the complete array of unique objects, you got a ref:
console.log(JSON.stringify(uniques));
.as-console-wrapper { min-height: 100%; }

의 추가 이점은 소스 개체와의 연결을 끊지 않고 고유하지 않은 항목을 잘라내 Map는 두 filter기능을 모두 얻을 수 있다는 것 입니다. 물론 고유 한 개체 집합을 여러 번 참조해야하는 경우에만 필요합니다.



2

ES6를 사용하면이 작업을 수행 할 수 있습니다.

var array=[
    {id:123, value:"value1", name:"Name1"},
    {id:124, value:"value2", name:"Name1"},
    {id:125, value:"value3", name:"Name2"},
    {id:126, value:"value4", name:"Name2"}
];

var set = new Set();

array.forEach((a)=>{
    set.add(a.name);
}); 

console.log(Array.from(set));


11
map부작용이 아닌 순수한 기능과 함께 사용되어야합니다. 이것은 forEach또는에 대한 직업입니다 reduce.
— Vincent van der Weele

1

UnderscoreJS 사용,

array = [{id:123, value:"value1", name:"Name1"}, {id:124, value:"value2", name:"Name1"}, {id:125, value:"value3", name:"Name2"}, {id:126, value:"value4", name:"Name2"}];
get_names =  _.pluck(_.uniq(array, 'name'), 'name')
console.log(get_names)
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

`


0

ES5에서는 O ( n ) 성능을 위한 사전으로 객체를 사용합니다 .

모든 키가 문자열 인 경우에만 작동합니다.

var array = [
    {id: 123, value: "value1", name: "Name1"},
    {id: 124, value: "value2", name: "Name1"},
    {id: 125, value: "value3", name: "Name2"},
    {id: 126, value: "value4", name: "Name2"}
];

var allNames = array.map(item => item.name);

var map = {};
allNames.forEach(name => {
  map[name] = true;
});
var uniqueNames = Object.keys(map);

console.log(uniqueNames);

원하는 경우 하나의 표현식에서 동일한 작업을 수행 할 수 있습니다.

var uniqueNames = Object.keys(allNames.reduce((m, n) => (m[n] = true, m), {}));

하지만 명령형이 더 읽기 쉽다는 것을 알았습니다.


명확성을 위해 ES6 화살표 기능을 사용했습니다. 트랜스 파일러없이 ES5를 실제로 대상으로하는 경우에는 대신 전체 양식을 사용해야합니다.function (item) { return item.name; }
— joeytwiddle

에 대한 대안으로 Object.keys(), 이 답변 은 filter()아직지도에 저장되지 않은 이름 만 유지하는 데 사용 되며 이는 매우 우아합니다.
— joeytwiddle


0

아직 최대의 호환성 을 원한다면 간결한 구문을 사용하려면 다음 array#forEach()과 array#indexOf()같은 방법을 사용하십시오 .

const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }]

// initialize an empty array named names
let names = [];

// iterate through every element of `array` & check if it's 'name' key's value already in names array if not ADD it 
array.forEach(function(element) { if (names.indexOf(element.name) === -1) names.push(element.name) });
// or use tilde like this:
//array.forEach(function(element) { if (~names.indexOf(element.name)) names.push(element.name) });

console.log(names);

그러나, 호환성이있는 경우는 문제에없는 사용은 6 ECMA 스크립트 의 Set객체 array#map와 Array.from()같은 방법 :

const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }];

// iterate through every element from array using map and store it in Set(a Set won't have duplicates) then convert the Set back to Array(using Array.from)
let names = Array.from(new Set(array.map(element => element.name)));

console.log(names);


0

그것이 별도의 빈 배열을 사용하여 내가 한 방법입니다.

var array = [
   {id:123, value:"value1", name:"Name1"},
   {id:124, value:"value2", name:"Name1"},
   {id:125, value:"value3", name:"Name2"},
   {id:126, value:"value4", name:"Name2"}	    
];

var array2 = []		
		
for (i=0; i<array.length;i++){						
   if (array2.indexOf(array[i].name) == -1){				
     array2.push(array[i].name);
    }
}			

console.log(array2)	


-1

1 라이너를 찾는 분

const names = array.reduce((acc, {name}) => acc.includes(name) ? acc : [name, ...acc], []);

또는 배열의 프로토 타입에서 메서드를 사용하지 않고

const { reduce, includes } = Array;
const names = reduce(array, (acc, {name}) => includes(acc, name) ? acc : [name, ...acc], []);

이를 처리하기위한 일부 순수 함수를 작성하는 데 유용 할 수 있습니다.

const get_uniq_values = (key, arr) => reduce(arr, (a, o) => includes(a, o[key]) ? a : [o[key], ...a], []);

-1
var __array=[{id:123, value:"value1", name:"Name1"},{id:124, value:"value2", name:"Name1"},{id:125, value:"value3", name:"Name2"},{id:126, value:"value4", name:"Name2"}];

function __checkArray(__obj){
    var flag = true;
    for(let i=0; i < __array.length; i++){
        if(__obj.id == __array.id){
            flag = false;
            break;
        }
    }

    return flag;
}

var __valToPush = {id: 127, value: "value5", name: "Name3"};
if(__checkArray(__valToPush)){
    __array.push(__valToPush)
}

11
밑줄을 너무 많이 사용하는 특별한 이유가 있습니까?
— Nina Scholz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.