JavaScript에서 객체 배열에서 중복 제거


373

객체 배열을 포함하는 객체가 있습니다.

things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

배열에서 중복 객체를 제거하는 가장 좋은 방법이 무엇인지 궁금합니다. 예를 들어, things.thing은 ...

{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}

배열에 동일한 매개 변수를 모두 추가하여 해시 테이블 / 객체를 어떻게 중지합니까?
Matthew Lock

1
Mathew-> 중복 객체가 처음에 배열에 추가되는 것을 방지하는 것이 더 간단하다면 나중에 필터링하지 않아도됩니다. 그렇습니다.
트래비스

2
사람들이 변수의 이름을 어떻게 지정하는지 놀랍습니다. 때로는 그들이 불필요하게 복잡하게 만들고 싶다고 생각합니다. 다음에 볼 것이다 aaaaa.aaaa.push(...):)
dazito

답변:


154

기본 방법은 다음과 같습니다.

var obj = {};

for ( var i=0, len=things.thing.length; i < len; i++ )
    obj[things.thing[i]['place']] = things.thing[i];

things.thing = new Array();
for ( var key in obj )
    things.thing.push(obj[key]);

15
for 루프에서 길이를 사용자가 사용하면 안됩니다. 반복 할 때마다 계산 속도가 느려지기 때문입니다. 루프 외부의 변수에 변수를 할당하고 things.thing.length 대신 변수를 전달하십시오.
0v3rth3d4wn 12

12
@aefxx이 기능을 잘 이해하지 못합니다. "장소"는 동일하지만 이름이 다른 상황을 어떻게 처리합니까?
Kuan

2
이것은 작동하지만 키 가져 오기는 순서가 보장되지 않으므로 정렬 된 배열을 처리하지 않습니다. 따라서 다시 정렬하게됩니다. 이제 배열이 정렬되지 않았지만 순서가 중요하다고 가정하면 순서가 그대로 유지되도록 할 수있는 방법이 없습니다
Deepak GM

1
@DeepakGM 당신은 절대적으로 맞습니다. 대답은 주어진 순서를 (필요하게) 보존하지 않습니다. 이것이 요구 사항이라면 다른 솔루션을 찾아야합니다.
aefxx

X를 포함하고 중복 제거되지 않은 배열에서 객체를 제거하기 위해 위의 내용을 어떻게 수정할 수 있습니까?
라이언 홀턴

435

어떻게 어떤 약 es6마법?

things.thing = things.thing.filter((thing, index, self) =>
  index === self.findIndex((t) => (
    t.place === thing.place && t.name === thing.name
  ))
)

참조 URL

보다 일반적인 해결책은 다음과 같습니다.

const uniqueArray = things.thing.filter((thing, index) => {
  const _thing = JSON.stringify(thing);
  return index === things.thing.findIndex(obj => {
    return JSON.stringify(obj) === _thing;
  });
});

Stackblitz 예


81
이것은 단축 할 수있다 :things.thing = things.thing.filter((thing, index, self) => self.findIndex(t => t.place === thing.place && t.name === thing.name) === index)
조쉬 콜을

완벽하게 작동합니다! var uniqueArrayOfObjects = arrayOfObjects.filter (function (obj, index, self) {return index === self.findIndex (function (t) {return t [ 'obj-property'] === obj [ 'obj-property'] });}); 올바른 JS 구문을 사용해야합니다.
모하메드 살렘 Lamiri

이것들은 올바른 JS 구문입니다. 귀하는 1) 지방 화살표 기능 2) 암시 적 반환 또는 3) 점 표기법을 사용하지 않습니다. 당신은 ES5 구문입니다. 나머지는 대부분 ES6 (ECMA2015)입니다. 모두 2017 년에 유효합니다. jaredwilli의 의견을 참조하십시오.
agm1984

8
@vsync는 @BKM의 대답을 취하여 종합하면 일반적인 해결책은 다음과 같습니다. const uniqueArray = arrayOfObjects.filter((object,index) => index === arrayOfObjects.findIndex(obj => JSON.stringify(obj) === JSON.stringify(object))); jsfiddle.net/x9ku0p7L/28
Eydrian

9
여기서 중요한 점은 findIndex () 메소드가 첫 번째 요소 의 색인을 리턴 하므로 일치하는 두 번째 요소가있는 경우 필터 중에 발견 및 추가되지 않습니다. 나는 그것을 잠시 쳐다보고 있었다 :)
JBaczuk

111

밑줄 이나 lodash 와 같은 Javascript 라이브러리를 사용할 수 있으면 _.uniq해당 라이브러리 에서 함수를 살펴 보는 것이 좋습니다 . 보낸 사람 lodash:

_.uniq(array, [isSorted=false], [callback=_.identity], [thisArg])

기본적으로 여기에 객체 리터럴이있는 배열을 전달하고 원래 데이터 배열에서 중복을 제거하려는 속성을 다음과 같이 전달합니다.

var data = [{'name': 'Amir', 'surname': 'Rahnama'}, {'name': 'Amir', 'surname': 'Stevens'}];
var non_duplidated_data = _.uniq(data, 'name'); 

업데이트 : Lodash는 이제도 도입했습니다 .uniqBy.


3
@Praveen Pds : 코드 예제에서 밑줄에 대해 말했습니까? 'lodash'에는이 기능이 있고 밑줄에는 비슷한 기능이 있다고 말했습니다. 투표하기 전에 답을주의 깊게 읽으십시오.
ambodi

// _underscore.js를 사용하여 고유 한 객체를 나열합니다. holdingObject = _.uniq (holdingObject, function (item, key, name) {return item.name;});
praveenpds

26
참고 : 이제 uniqBy대신 문서 를 사용해야 합니다 uniq. 예 : _.uniqBy(data, 'name')... documentation : lodash.com/docs#uniqBy
drmrbrewer

82

단일 필드의 중복을 기반으로 배열에서 중복 객체를 제거 해야하는 것과 동일한 요구 사항이 있습니다. 여기에서 코드를 찾았습니다 : Javascript : 객체 배열에서 중복 제거

따라서 내 예제에서는 licenseNum 문자열 값이 중복 된 배열에서 객체를 제거하고 있습니다.

var arrayWithDuplicates = [
    {"type":"LICENSE", "licenseNum": "12345", state:"NV"},
    {"type":"LICENSE", "licenseNum": "A7846", state:"CA"},
    {"type":"LICENSE", "licenseNum": "12345", state:"OR"},
    {"type":"LICENSE", "licenseNum": "10849", state:"CA"},
    {"type":"LICENSE", "licenseNum": "B7037", state:"WA"},
    {"type":"LICENSE", "licenseNum": "12345", state:"NM"}
];

function removeDuplicates(originalArray, prop) {
     var newArray = [];
     var lookupObject  = {};

     for(var i in originalArray) {
        lookupObject[originalArray[i][prop]] = originalArray[i];
     }

     for(i in lookupObject) {
         newArray.push(lookupObject[i]);
     }
      return newArray;
 }

var uniqueArray = removeDuplicates(arrayWithDuplicates, "licenseNum");
console.log("uniqueArray is: " + JSON.stringify(uniqueArray));

결과 :

uniqueArray는 다음과 같습니다.

[{"type":"LICENSE","licenseNum":"10849","state":"CA"},
{"type":"LICENSE","licenseNum":"12345","state":"NM"},
{"type":"LICENSE","licenseNum":"A7846","state":"CA"},
{"type":"LICENSE","licenseNum":"B7037","state":"WA"}]

1
함수가 '거짓'객체도 필터링 할 수있는 경우에 더 유용합니다. for(var i in array) { if(array[i][prop]){ //valid lookupObject[array[i][prop]] = array[i]; } else { console.log('falsy object'); } }
압둘 사딕 얄친

다음을 사용하여 복잡도 0 (n)을 줄이십시오. for (let i in originalArray) { if (lookupObject[originalArray[i]['id']] === undefined) { newArray.push(originalArray[i]); } lookupObject[originalArray[i]['id']] = originalArray[i]; }
Tudor B.

복제하지 않으려는 것이 무엇인지 아는 것이 중요하기 때문에 이것이 가장 좋은 방법입니다. 이제 e6 표준 용 감속기를 통해이 작업을 수행 할 수 있습니까?
Christian Matthew

69

ES6 + 용 최단 라이너

id배열에서 고유 한를 찾으십시오 .

arr.filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i)

여러 속성 ( placename)으로 고유

arr.filter((v,i,a)=>a.findIndex(t=>(t.place === v.place && t.name===v.name))===i)

모든 속성에 고유함 (대형 배열의 경우 속도가 느림)

arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)

마지막 발생을 유지하십시오.

arr.slice().reverse().filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i).reverse()

2
마술, 이것은 정답입니다
Luis Contreras

48

Set을 사용하는 하나의 라이너

var things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

// assign things.thing to myData for brevity
var myData = things.thing;

things.thing = Array.from(new Set(myData.map(JSON.stringify))).map(JSON.parse);

console.log(things.thing)

설명:

  1. new Set(myData.map(JSON.stringify))세트를 만듭니다문자열 화 된 myData 요소를 사용하여 객체를 .
  2. 객체 설정은 모든 요소가 고유한지 확인합니다.
  3. 그런 다음 Array.from을 사용하여 생성 된 집합의 요소를 기반으로 배열을 만듭니다.
  4. 마지막으로 JSON.parse를 사용하여 문자열 화 된 요소를 다시 개체로 변환합니다.

18
{a : 1, b : 2}라는 문제는 {b : 2, a : 1}과 같지 않습니다
PirateApp

2
Date 속성에 문제가있을 수 있음을 명심하십시오
MarkosyanArtur

이 줄은 원래 객체 배열에없는 행 객체로 임의의 null 값을 만듭니다. 도와주세요?
B1K

46

한 줄에 ES6 + 를 사용하면 키를 사용 하여 고유 한 객체 목록을 얻을 수 있습니다.

const unique = [...new Map(arr.map(item => [item[key], item])).values()]

함수에 넣을 수 있습니다.

function getUniqueListBy(arr, key) {
    return [...new Map(arr.map(item => [item[key], item])).values()]
}

다음은 실제 예입니다.

const arr = [
    {place: "here",  name: "x", other: "other stuff1" },
    {place: "there", name: "x", other: "other stuff2" },
    {place: "here",  name: "y", other: "other stuff4" },
    {place: "here",  name: "z", other: "other stuff5" }
]

function getUniqueListBy(arr, key) {
    return [...new Map(arr.map(item => [item[key], item])).values()]
}

const arr1 = getUniqueListBy(arr, 'place')

console.log("Unique by place")
console.log(JSON.stringify(arr1))

console.log("\nUnique by name")
const arr2 = getUniqueListBy(arr, 'name')

console.log(JSON.stringify(arr2))

작동 원리

먼저 배열을 지도 의 입력으로 사용할 수있는 방식으로 다시 매핑 합니다.

arr.map (항목 => [항목 [키], 항목]);

즉, 배열의 각 항목이 2 개의 요소가있는 다른 배열로 변환됩니다. 선택한 키 첫번째 요소로서 전체 초기 항목 번째 요소로서,이 항목 (예.이라고 배열 엔트리 , 맵 엔트리 ). 그리고 여기 공식 문서가 있습니다 지도 생성자에 배열 항목을 추가하는 방법을 보여주는 예제와 함께.

키가 배치 된 예 :

[["here", {place: "here",  name: "x", other: "other stuff1" }], ...]

두 번째로,이 수정 된 배열을 Map 생성자에 전달하면 마술이 일어납니다. Map은 중복 키 값을 제거하고 동일한 키의 마지막 삽입 값만 유지합니다. 참고 : Map은 삽입 순서를 유지합니다. ( 지도와 객체의 차이점 확인 )

새 맵 (위에 방금 매핑 한 항목 배열)

셋째, 맵 값을 사용하여 원래 항목을 검색하지만 이번에는 중복되지 않습니다.

새 맵 (mappedArr) .values ​​()

마지막으로,이 값을 새로운 배열에 추가하여 초기 구조로보고 다음을 반환합니다.

[... 새 맵 (mappedArr) .values ​​()] 반환


이 검색은 원래 질문에 대한 답변이 아닙니다 id. 문제는 모든 분야에 걸쳐 고유하기 위해 전체 개체를 필요로 place하고name
L. Holanda

ES6 기능은 매우 간결하고 실용적입니다. 좀 더 설명해 주시겠습니까? 정확히 무슨 일이야? 첫 번째 또는 마지막 중복이 제거 되었습니까? 또는 무작위로 어떤 복제본이 제거됩니까? 도움이 될 것입니다. 감사합니다.
David Schumann

내가 알 수있는 한 속성 값을 키로 사용하여 맵이 생성됩니다. 그러나 배열의 순서가 어떻게 또는 유지되는지는 100 %가 아닙니다.
David Schumann

1
안녕하세요 @DavidSchumann, 답변을 업데이트하고 작동 방법을 설명합니다. 그러나 짧은 대답에 대한 순서가 보존되어 제거된다 첫 번째는 ... 그냥이 맵에 삽입하는 방법에 대해 생각 ... 그것은 키는 이미 마지막이 therfore 남아, 그것을 업데이트됩니다 존재를 확인하는 경우
V를 삼보

30

다음은 객체의 한 필드 만 비교해야하는 경우 Array iterating 메서드를 사용하여 수행하는 또 다른 옵션입니다.

    function uniq(a, param){
        return a.filter(function(item, pos, array){
            return array.map(function(mapItem){ return mapItem[param]; }).indexOf(item[param]) === pos;
        })
    }

    uniq(things.thing, 'place');

이 순서는 O (n²)보다 크지 만 배열 크기가 항상 30보다 작기 때문에 유스 케이스에 적합합니다. 감사합니다!
Sterex

24

하나의 라이너가 여기 있습니다

let arr = [
  {id:1,name:"sravan ganji"},
  {id:2,name:"anu"},
  {id:4,name:"mammu"},
  {id:3,name:"sanju"},
  {id:3,name:"ram"},
];

console.log(Object.values(arr.reduce((acc,cur)=>Object.assign(acc,{[cur.id]:cur}),{})))


1
단일 복제 값으로 만 개체를 ​​제거하려는 경우 멋지고 깨끗합니다. 완전히 복제 된 개체에는 그렇게 깨끗하지 않습니다.
David Barker

22

모든 추가가 끝날 때까지 중복 제거를 기다릴 수있는 경우 일반적인 방법은 먼저 배열을 정렬 한 다음 중복을 제거하는 것입니다. 정렬은 각 요소를 통해 배열을 스캔 할 때 N * N 접근 방식을 피합니다.

"중복 제거"기능은 일반적으로 unique 또는 uniq 이라고 합니다 . 기존의 일부 구현은 두 단계를 결합 할 수 있습니다 (예 : 프로토 타입의 유니크)

이 게시물 에는 라이브러리에 아직 아이디어가없는 경우 시도 할 아이디어가 거의 없습니다 . 개인적으로 나는 이것이 가장 직설적이라고 생각합니다.

    function unique(a){
        a.sort();
        for(var i = 1; i < a.length; ){
            if(a[i-1] == a[i]){
                a.splice(i, 1);
            } else {
                i++;
            }
        }
        return a;
    }  

    // Provide your own comparison
    function unique(a, compareFunc){
        a.sort( compareFunc );
        for(var i = 1; i < a.length; ){
            if( compareFunc(a[i-1], a[i]) === 0){
                a.splice(i, 1);
            } else {
                i++;
            }
        }
        return a;
    }

자연스러운 정렬 순서가없는 일반 객체에는 작동하지 않습니다.
Tim Down

사실, 사용자 제공 비교 버전을 추가했습니다.
maccullt

사용자가 제공 한 비교 버전은 작동하지 않습니다. 비교 기능이 있으면 function(_a,_b){return _a.a===_b.a && _a.b===_b.b;}배열이 정렬되지 않기 때문입니다.
graham.reeds

1
잘못된 비교 함수입니다. 가입일 developer.mozilla.org/en/Core_JavaScript_1.5_Reference/... 비교 ... 함수 (a, b) 경우에 {(a 적은 일부 정렬 기준에 의해보다 B) -1을 리턴; (a가 순서 기준에 의해 b보다 큰 경우) 1을 리턴하고; // a는 b와 같아야합니다. return 0; } ...
maccullt

22

가장 간단한 방법은 filter다음과 같습니다.

var uniq = {}
var arr  = [{"id":"1"},{"id":"1"},{"id":"2"}]
var arrFiltered = arr.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));
console.log('arrFiltered', arrFiltered)


6
솔루션이 왜 작동해야하는지, 특히 다른 솔루션보다 솔루션이 더 나은 방법에 대한 설명을 추가하는 것이 Stack Overflow의 모범 사례입니다. 자세한 내용은 답변 방법을 참조하십시오 .
Samuel Liew

이 검색은 원래 질문에 대한 답변이 아닙니다 id. 문제는 모든 분야에 걸쳐 고유하기 위해 전체 개체를 필요로 place하고name
L. Holanda

16

이것은 일반적인 방법입니다. 배열의 두 요소가 같은지 여부를 테스트하는 함수를 전달합니다. 이 경우 비교 중인 두 개체 의 nameplace속성 값을 비교합니다.

ES5 답변

function removeDuplicates(arr, equals) {
    var originalArr = arr.slice(0);
    var i, len, val;
    arr.length = 0;

    for (i = 0, len = originalArr.length; i < len; ++i) {
        val = originalArr[i];
        if (!arr.some(function(item) { return equals(item, val); })) {
            arr.push(val);
        }
    }
}

function thingsEqual(thing1, thing2) {
    return thing1.place === thing2.place
        && thing1.name === thing2.name;
}

var things = [
  {place:"here",name:"stuff"},
  {place:"there",name:"morestuff"},
  {place:"there",name:"morestuff"}
];

removeDuplicates(things, thingsEqual);
console.log(things);

원래 ES3 답변

function arrayContains(arr, val, equals) {
    var i = arr.length;
    while (i--) {
        if ( equals(arr[i], val) ) {
            return true;
        }
    }
    return false;
}

function removeDuplicates(arr, equals) {
    var originalArr = arr.slice(0);
    var i, len, j, val;
    arr.length = 0;

    for (i = 0, len = originalArr.length; i < len; ++i) {
        val = originalArr[i];
        if (!arrayContains(arr, val, equals)) {
            arr.push(val);
        }
    }
}

function thingsEqual(thing1, thing2) {
    return thing1.place === thing2.place
        && thing1.name === thing2.name;
}

removeDuplicates(things.thing, thingsEqual);

1
두 개의 객체가 동일한 속성과 값을 공유하더라도 동일하게 평가되지 않습니다.
kennebec

예, 알아요 그러나 공정한 요점, 나는 질문을 올바르게 읽지 못했습니다. 답변을 편집하겠습니다.
Tim Down

1
arrayContains 내부에있는 대신 Array.prototype..some 메서드 사용 배열 멤버 중 하나가 조건과 일치하면 true를 반환합니다.
MarkosyanArtur

13

목록에 하나 더 추가합니다. ES6 및 사용 Array.reduce과를 Array.find.
이 예에서는 guid속성을 기준으로 객체를 필터링합니다 .

let filtered = array.reduce((accumulator, current) => {
  if (! accumulator.find(({guid}) => guid === current.guid)) {
    accumulator.push(current);
  }
  return accumulator;
}, []);

이 속성을 확장하여 속성을 선택하고 하나의 라이너로 압축 할 수 있습니다.

const uniqify = (array, key) => array.reduce((prev, curr) => prev.find(a => a[key] === curr[key]) ? prev : prev.push(curr) && prev, []);

이것을 사용하려면 객체 배열과 중복 제거하려는 키의 이름을 문자열 값으로 전달하십시오.

const result = uniqify(myArrayOfObjects, 'guid')

11

당신은 또한 사용할 수 있습니다 Map:

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

전체 샘플 :

const things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

console.log(JSON.stringify(dedupThings, null, 4));

결과:

[
    {
        "place": "here",
        "name": "stuff"
    },
    {
        "place": "there",
        "name": "morestuff"
    }
]

+1, dedup의 내부 작업이 조금 더 잘 설명 될 수있는 좋은 방법-밝은면에서 내가 줄인 것 같습니다 : D
MimiEAM

11

댕, 애들 아, 이거 뭉개 보자, 우리 왜?

let uniqIds = {}, source = [{id:'a'},{id:'b'},{id:'c'},{id:'b'},{id:'a'},{id:'d'}];
let filtered = source.filter(obj => !uniqIds[obj.id] && (uniqIds[obj.id] = true));
console.log(filtered);
// EXPECTED: [{id:'a'},{id:'b'},{id:'c'},{id:'d'}];


이 검색은 원래 질문에 대한 답변이 아닙니다 id. 문제는 모든 분야에 걸쳐 고유하기 위해 전체 개체를 필요로 place하고name
L. Holanda

이것은 위에서 언급 한 문제의 일반화입니다. 원래 포스터는 아마 걱정되지 않도록 원래의 질문은 9 년 전에 게시 placename오늘. 이 스레드를 읽는 사람은 객체 목록을 중복 제거하는 최적의 방법을 찾고 있으며 이는 간단한 방법입니다.
Cliff Hall

11

TypeScript 솔루션

이렇게하면 중복 객체가 제거되고 객체 유형도 보존됩니다.

function removeDuplicateObjects(array: any[]) {
  return [...new Set(array.map(s => JSON.stringify(s)))]
    .map(s => JSON.parse(s));
}

2
이것은 위대하고 짧습니다!
mojjj

그리고 슈퍼 슬로우 너무 ...
L. Holanda

7

고려하면 lodash.uniqWith

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

_.uniqWith(objects, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]

완벽 해! 감사합니다 ;-)
DonFabiolas

1
lodash의 uniq 또는 uniqBy가 트릭을 수행하지는 않았지만 솔루션은 그랬습니다. 감사! 직접 코드 인 경우 코드 소스를 제공하십시오. lodash.com/docs/4.17.10#uniqWith
Manu CJ

5

다른 옵션은 사용자 정의 indexOf 함수를 작성하는 것입니다.이 함수는 각 오브젝트에 대해 선택한 특성 값을 비교하고이를 감소 함수로 랩핑합니다.

var uniq = redundant_array.reduce(function(a,b){
      function indexOfProperty (a, b){
          for (var i=0;i<a.length;i++){
              if(a[i].property == b.property){
                   return i;
               }
          }
         return -1;
      }

      if (indexOfProperty(a,b) < 0 ) a.push(b);
        return a;
    },[]);

이것은 나에게 큰 도움이되었습니다. 나는 이것을 lodash.isequalnpm 패키지 와 가벼운 객체 비교기로 결합하여 독특한 배열 필터링을 수행합니다 (예 : 독특한 객체 배열). 그냥에서 교환 if (_.isEqual(a[i], b)) {대신에 하나의 속성 @ 보는
SliverNinja - MSFT에게

5

let myData = [{place:"here",name:"stuff"}, 
 {place:"there",name:"morestuff"},
 {place:"there",name:"morestuff"}];


let q = [...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];

console.log(q)

ES6 및을 사용하는 하나의 라이너 new Map().

// assign things.thing to myData
let myData = things.thing;

[...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];

세부:-

  1. 이렇게 .map()데이터 목록 및 각 객체로 변환 [key, value]쌍 배열 (길이 = 2)의 첫 번째 요소 (키)가 될 stringified객체 및 제 (값)적인 버전 일 것object 자체.
  2. 위에서 만든 배열 목록을 추가 new Map()하면 키가 stringified객체로 사용되며 동일한 키를 추가하면 이미 존재하는 키가 재정의됩니다.
  3. 를 사용하면 .values()MapIterator에 Map의 모든 값이 제공됩니다 (obj 이 경우)
  4. 마지막으로 spread ...연산자는 위 단계의 값으로 새 Array를 제공합니다.

4

마지막 항목 만 유지하려는 es6 솔루션이 있습니다. 이 솔루션은 기능적이고 에어 비앤비 스타일을 준수합니다.

const things = {
  thing: [
    { place: 'here', name: 'stuff' },
    { place: 'there', name: 'morestuff1' },
    { place: 'there', name: 'morestuff2' }, 
  ],
};

const removeDuplicates = (array, key) => {
  return array.reduce((arr, item) => {
    const removed = arr.filter(i => i[key] !== item[key]);
    return [...removed, item];
  }, []);
};

console.log(removeDuplicates(things.thing, 'place'));
// > [{ place: 'here', name: 'stuff' }, { place: 'there', name: 'morestuff2' }]

복제본을 제거 할 수 있으며이 코드로 모든 복제본을 제거 할 수도 있습니다. 니스
sg28

4

removeDuplicates ()는 객체 배열을 가져오고 id 속성을 기반으로 중복 객체없이 새 배열을 반환합니다.

const allTests = [
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'},
  {name: 'Test2', id: '2'},
  {name: 'Test3', id: '3'}
];

function removeDuplicates(array) {
  let uniq = {};
  return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true))
}

removeDuplicates(allTests);

예상되는 결과:

[
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'}
];

먼저 변수 uniq의 값을 빈 객체로 설정합니다.

다음으로 객체 배열을 필터링합니다. Filter는 제공된 함수로 구현 된 테스트를 통과하는 모든 요소를 ​​사용하여 새 배열을 만듭니다.

return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));

위에서는 &&의 단락 기능을 사용합니다. &&의 왼쪽이 true로 평가되면 &&의 오른쪽에있는 값을 리턴합니다. 왼쪽이 거짓이면 &&의 왼쪽에있는 것을 반환합니다.

각 객체 (obj)에 대해 uniq에 obj.id라는 값의 속성이 있는지 확인합니다 (이 경우 첫 번째 반복에서는 속성 '1'을 확인합니다). 또는 거짓) 그래서 우리는! ! uniq [obj.id]에서 uniq에 id 속성이 이미 있으면 true를 반환하여 필터 함수에 해당 obj를 추가하지 말라고 false (!)로 평가합니다. 그러나 obj.id 속성을 찾지 못하면 false를 반환 한 다음 true (!)로 평가하고 &&의 오른쪽으로 모든 것을 반환합니다 (uniq [obj.id] = true). 이 값은 필터 메소드에 해당 obj를 리턴 된 배열에 추가하도록 지시하는 값이며, {1 : true} 특성을 uniq에 추가합니다. 이렇게하면 동일한 ID를 가진 다른 obj 인스턴스가 다시 추가되지 않습니다.


아마도 코드를 설명하고 질문에 어떻게 대답합니까?
mix3d

고마워, mix3d. 설명을 추가했습니다.
MarkN

이것을 설명해 주셔서 감사합니다! 이 솔루션은 저에게 효과적이며 여기에 게시 된 다른 몇 가지와 유사하지만 어떤 일이 일어나고 있는지 이해하지 못했습니다 :)
Tim Molloy

3
let data = [
  {
    'name': 'Amir',
    'surname': 'Rahnama'
  }, 
  {
    'name': 'Amir',
    'surname': 'Stevens'
  }
];
let non_duplicated_data = _.uniqBy(data, 'name');

9
향후 방문자가 자신이하는 일을 이해할 수 있도록 코드 주위에 설명을 추가하십시오. 감사.
버그

귀하의 답변은 외부 코드 라이브러리에 따라 다릅니다 ...
Taylor A. Leach

3

나는의 조합을 생각 reduceJSON.stringify완벽하게 비교 개체 및 선택적으로 축적에없는 사람들을 추가하는 우아한 방법입니다.

JSON.stringify어레이에 많은 객체가 있고 대부분의 경우 복잡하지만 극한의 경우 성능 문제가 될 수 있음을 명심하십시오 .

var collection= [{a:1},{a:2},{a:1},{a:3}]

var filtered = collection.reduce((filtered, item) => {
  if( !filtered.some(filteredItem => JSON.stringify(filteredItem) == JSON.stringify(item)) )
    filtered.push(item)
  return filtered
}, [])

console.log(filtered)

동일하지만 덜 효율적인 다른 방법 :

collection.reduce((filtered, item) => 
  filtered.some(filteredItem => 
    JSON.stringify(filteredItem ) == JSON.stringify(item)) 
      ? filtered
      : [...filtered, item]
, [])

나를 위해 일하는 사람! 감사합니다!
javascript110899

2

객체 배열에서 중복을 제거하는 ES6 방법을 계속 탐색합니다. thisArg인수를 설정 하여 적절한 대안 Array.prototype.filternew Set제공하십시오.

const things = [
  {place:"here",name:"stuff"},
  {place:"there",name:"morestuff"},
  {place:"there",name:"morestuff"}
];

const filtered = things.filter(function({place, name}) {

  const key =`${place}${name}`;

  return !this.has(key) && this.add(key);

}, new Set);

console.log(filtered);

그러나 어휘 범위에 바인딩 된 화살표 함수 () =>에서는 작동하지 않습니다 this.


2

es6 마술 한 줄에 ... 그것에서 읽을 수 있습니다!

// returns the union of two arrays where duplicate objects with the same 'prop' are removed
const removeDuplicatesWith = (a, b, prop) => a.filter(x => !b.find(y => x[prop] === y[prop]);

2

ES6 'reduce'및 'find'어레이 헬퍼 메소드를 사용한 간단한 솔루션

효율적이고 완벽하게 작동합니다!

"use strict";

var things = new Object();
things.thing = new Array();
things.thing.push({
    place: "here",
    name: "stuff"
});
things.thing.push({
    place: "there",
    name: "morestuff"
});
things.thing.push({
    place: "there",
    name: "morestuff"
});

// the logic is here

function removeDup(something) {
    return something.thing.reduce(function (prev, ele) {
        var found = prev.find(function (fele) {
            return ele.place === fele.place && ele.name === fele.name;
        });
        if (!found) {
            prev.push(ele);
        }
        return prev;
    }, []);
}
console.log(removeDup(things));

이 많은 저를 도와, 감사합니다
jpisty

1

나중에 고유 한 배열을 정렬하는 데 신경 쓰지 않으면 효율적인 솔루션이 될 것입니다.

things.thing
  .sort(((a, b) => a.place < b.place)
  .filter((current, index, array) =>
    index === 0 || current.place !== array[index - 1].place)

이렇게하면 현재 요소와 배열의 이전 요소 만 비교하면됩니다. 필터링하기 전에 한 번 정렬하면 ( O(n*log(n))) 모든 배열 요소 ( O(n²)) 에 대해 전체 배열에서 중복을 검색하는 것보다 저렴 합니다.


1

이것은 객체 배열에서 이중성을 제거하는 간단한 방법입니다.

나는 데이터를 많이 다루고 있으며 이것은 나에게 유용하다.

const data = [{name: 'AAA'}, {name: 'AAA'}, {name: 'BBB'}, {name: 'AAA'}];
function removeDuplicity(datas){
    return datas.filter((item, index,arr)=>{
    const c = arr.map(item=> item.name);
    return  index === c.indexOf(item.name)
  })
}

console.log(removeDuplicity(data))

콘솔에 인쇄합니다 :

[[object Object] {
name: "AAA"
}, [object Object] {
name: "BBB"
}]

이 솔루션은 정적 배열에서 중복성을 제거하도록 설계되었지만 백엔드에서 데이터 배열로 데이터를 푸시하면 replace 사용을 고려하십시오. 이 경우 데이터 배열에 푸시 된 새 값이 제거되고 "이전"값은 여전히 ​​데이터 배열에 저장됩니다.
Juraj

1
str =[
{"item_id":1},
{"item_id":2},
{"item_id":2}
]

obj =[]
for (x in str){
    if(check(str[x].item_id)){
        obj.push(str[x])
    }   
}
function check(id){
    flag=0
    for (y in obj){
        if(obj[y].item_id === id){
            flag =1
        }
    }
    if(flag ==0) return true
    else return false

}
console.log(obj)

str 은 객체의 배열입니다. 동일한 값을 가진 객체가 있습니다 (여기서는 작은 예에서는 item_id가 2 인 객체가 두 개 있습니다). check (id) 는 item_id가 같은 객체가 있는지 확인하는 함수입니다. 존재하는 경우 false를 리턴하고 그렇지 않으면 true를 리턴하십시오. 그 결과에 따라 객체를 새로운 배열로 밀어 넣습니다. obj 위 코드의 출력은 [{"item_id":1},{"item_id":2}]


설명 추가
Mathews Sunny

@ 빌라 괜찮아?
Bibin Jaimon

1

Lodash 도서관에 대해 들어 보셨습니까? 논리를 코드에 적용하고 싶지 않고 최적화되고 신뢰할 수있는 이미 존재하는 코드를 사용하고 싶을 때이 유틸리티를 사용하는 것이 좋습니다.

이런 배열을 만들어보십시오

things.thing.push({place:"utopia",name:"unicorn"});
things.thing.push({place:"jade_palace",name:"po"});
things.thing.push({place:"jade_palace",name:"tigress"});
things.thing.push({place:"utopia",name:"flying_reindeer"});
things.thing.push({place:"panda_village",name:"po"});

하나의 속성을 고유하게 유지하려면 lodash 라이브러리를 사용하여 잘 수행 할 수 있습니다. 여기서 _.uniqBy를 사용할 수 있습니다

.uniqBy (배열, [iteratee = .identity])

이 메소드는 _.uniq (각 요소의 첫 번째 항목 만 유지되는 중복없는 버전의 배열을 리턴 함 )와 유사 합니다. 고유성이 계산됩니다.

예를 들어 'place'의 고유 한 속성을 가진 배열을 반환하려는 경우

_.uniqBy (things.thing, 'place')

마찬가지로 'name'으로 고유 한 속성을 원할 경우

_.uniqBy (things.thing, 'name')

도움이 되었기를 바랍니다.

건배!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.