JavaScriptでオブジェクトの配列から重複を削除する


374

オブジェクトの配列を含むオブジェクトがあります。

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"}

配列に追加されているすべての同じパラメーターでハッシュテーブル/オブジェクトをどのように停止するのですか?
マシューロック

1
Mathew->最初に重複するオブジェクトが配列に追加されないようにするほうが簡単で、後でフィルターで除外するよりも簡単であれば、そうです。
Travis

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 2014

12
@aefxx私はこの機能を完全に理解していません。「場所」は同じだが名前が異なるという状況をどのように処理しますか、それはdupを考慮すべきですか?
Kuan

2
これは機能しますが、キーのフェッチは順序が保証されないため、ソートされた配列は処理されません。だから、あなたは再びそれをソートすることになります。ここで、配列が並べ替えられていないが、その順序が重要であるとします。順序が変更されていないことを確認する方法はありません
Deepak GM

1
@DeepakGMあなたは絶対的に正しいです。答えは与えられた順序を(必然的に)維持しません。それが要件である場合、別のソリューションを探す必要があります。
aefxx

Xを含み、重複除外された配列からオブジェクトを削除するために、上記をどのように変更できますか?
Ryan Holton

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構文を使用していることを確認してください。
Mohamed Salem Lamiri 2017年

これらは適切なJS構文です。あなたは1)ファットアロー関数2)暗黙のリターンまたは3)ドット表記を使用していません。あなたのものはES5構文です。その他は主にES6(ECMA2015)です。すべて2017年に有効です。jaredwilliのコメントを参照してください。
agm1984 2017年

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()メソッドが最初の要素のインデックスを返すことです。そのため、一致する2番目の要素がある場合、それがフィルター中に検出されて追加されることはありません。私は1分間それをじっと見つめていた:)
JBaczuk '13

111

アンダースコアやロダッシュなどの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 2015年

// _underscore.jsを使用して一意のオブジェクトを一覧表示するholdingObject = _.uniq(holdingObject、function(item、key、name){return item.name;});
praveenpds

26
注:たとえば...のuniqBy代わりにを使用する必要があります...ドキュメント:lodash.com/docs#uniqByuniq_.uniqBy(data, 'name')
drmrbrewer

83

単一のフィールドの重複に基づいて、配列内の重複オブジェクトを削除するという、これとまったく同じ要件がありました。私はここにコードを見つけました: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'); } }
Abdul Sadik Yalcin 2017年

以下を使用して、複雑さ0(n)を下げないのはなぜですか for (let i in originalArray) { if (lookupObject[originalArray[i]['id']] === undefined) { newArray.push(originalArray[i]); } lookupObject[originalArray[i]['id']] = originalArray[i]; }
チューダーB.

複製したくないことを理解することが重要であるため、これが最良の方法です。これはe6標準のレデューサーを介して実行できますか?
クリスチャンマシュー

70

ES6 +の最短ワンライナー

id配列から一意のを見つけます。

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

複数のプロパティで一意(placeおよびname

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
マジック、これが本当の答えは
ルイス・コントレラス

48

セットを使用した1つのライナー

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要素を使用してSetオブジェクトを作成します。
  2. Setオブジェクトは、すべての要素が一意であることを保証します。
  3. 次に、Array.fromを使用して、作成したセットの要素に基づいて配列を作成します。
  4. 最後に、JSON.parseを使用して文字列化された要素をオブジェクトに変換します。

18
{a:1、b:2}の問題は{b:2、a:1}と等しくありません
PirateApp

2
Dateプロパティに問題があることに注意してください
MarkosyanArtur 2018年

この行は、オブジェクトの元の配列に存在しない行オブジェクトでランダムなnull値を作成します。手伝ってくれませんか?
B1K 2018年

46

ES6 +を1行で使用すると、キーによってオブジェクトの一意のリストを取得できます。

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(item => [item [key]、item]);

これは、配列の各項目が2つの要素を持つ別の配列に変換されることを意味します。選択されたキーの最初の要素とのような全体の初期アイテム第二の要素としては、これは、エントリ(例:と呼ばれる配列エントリマップエントリ)。そして、これはMapコンストラクタに配列エントリを追加する方法を示す例を含む公式のドキュメントです。

キーが配置されている場合の例:

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

次に、この変更された配列をMapコンストラクターに渡します。これが魔法の出来事です。マップは、重複するキー値を排除し、同じキーの最後に挿入された値のみを保持します。 :マップは挿入の順序を保持します。(マップとオブジェクトの違いを確認してください

新しいマップ(上記のマップされたエントリ配列)

3番目に、元のアイテムを取得するためにマップ値を使用しますが、今回は重複なしです。

新しいMap(mappedArr).values()

そして最後に、これらの値を新しい新しい配列に追加して、それが初期構造として見え、それを返すことができるようにします。

return [... new Map(mappedArr).values()]


これはを検索するため、元の質問には答えませんidplaceandのようなすべてのフィールドにわたってオブジェクト全体が一意である必要がありますname
L. Holanda

ES6の機能は非常に簡潔で実用的です。もう少し説明してもらえますか?正確には何が起こっていますか?最初または最後の重複は削除されますか?それともランダムですか、どの重複が削除されますか?よろしくお願いいたします。
David Schumann

私が知る限り、キーとしてプロパティ値を持つマップが作成されます。しかし、配列の順序が保持されるかどうかは、100%ではありません。
David Schumann

1
こんにちは@DavidSchumann、私は答えを更新し、それがどのように機能するかを説明します。しかし、短い答えの場合、順序は保持され、最初の順序は削除されます...それがマップにどのように挿入されるかを考えてください...キーがすでに存在するかどうかをチェックし、更新します。したがって、最後の順序は残ります
V 。サンボー

30

オブジェクトの1つのフィールドのみによる比較が必要な場合は、配列反復メソッドを使用してそれを行う別のオプションを次に示します。

    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と呼ばれます。一部の既存の実装では、2つのステップを組み合わせることができます。たとえば、プロトタイプの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

確かに、ユーザー提供の比較バージョンを追加しました。
マカルト

ユーザー提供の比較バージョンは機能しません。比較関数がそうであるfunction(_a,_b){return _a.a===_b.a && _a.b===_b.b;}場合、配列はソートされないためです。
graham.reeds 2010年

1
これは無効な比較関数です。developer.mozilla.org/en/Core_JavaScript_1.5_Reference/…から ...関数compare(a、b){if(aが何らかの順序付け基準でbより小さい場合)return -1; if(aが順序付け基準でbよりも大きい場合)1を返す。// aはbと等しい必要がありますreturn 0; } ...
maccullt 2010年

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

これはを検索するため、元の質問には答えませんidplaceandのようなすべてのフィールドでオブジェクト全体が一意である必要がありますname
L. Holanda

17

これは、これを行う一般的な方法です。配列の2つの要素が等しいと見なされるかどうかをテストする関数を渡します。この場合、比較される2つのオブジェクトのnameおよびplaceプロパティの値を比較します。

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
2つのオブジェクトは、同じプロパティと値を共有していても、同等に評価されません。
ケネベック2010

はい、知っています。しかし、公平に言えば、私は質問を正しく読むことができませんでした。彼が取り除く必要のある同一のプロパティを持つオブジェクトであることに気づきませんでした。回答を編集します。
Tim Down

1
arrayContainsの内部ではなく、Array.prototype..someメソッドを使用します。配列のメンバーの1つが条件に一致する場合にtrueを返します
MarkosyanArtur

13

リストにもう1つ追加します。ES6とArray.reduceを使用しArray.findます。
この例では、guidプロパティに基づいてオブジェクトをフィルタリングしています。

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

これを拡張してプロパティを選択し、1つのライナーに圧縮します。

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、dedupThingsの内側の作業が良いでしょう、もう少し説明カントー素敵-明るい側に私が今減らす理解: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。質問は、以下のようなすべてのフィールド全体で一意であるオブジェクト全体を必要placename
L. Holandaの

これは、上記の問題の一般化の改良版です。オリジナルポスターは、おそらく心配されていないので、元の質問は、9年前に投稿されましたplaceし、name今日。このスレッドを読む人は、オブジェクトのリストを重複排除する最適な方法を探しています。これは、コンパクトな方法です。
クリフホール

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 2018

1
lodashのuniqもuniqByもトリックをしませんでしたが、あなたの解決策はしました。ありがとう!ただし、直接コピーの場合は、コードのソースをお知らせください。lodash.com/docs/4.17.10#uniqWith
Manu CJ

5

別のオプションは、カスタムindexOf関数を作成することです。これは、各オブジェクトの選択したプロパティの値を比較し、これをreduce関数でラップします。

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)) {の代わりに、単一のプロパティ@探して
MSFT - SliverNinja

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 ...上記の手順の値で新しい配列を与えるための演算子。

4

最後のアイテムのみを保持したいes6のソリューションを次に示します。このソリューションは機能的で、Airbnbスタイルに準拠しています。

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と評価された場合、&&の右側の値を返します。左側がfalseの場合、&&の左側にあるものを返します。

各オブジェクト(obj)について、obj.idの値という名前のプロパティについてuniqをチェックします(この場合、最初の反復では、プロパティ '1'をチェックします)。またはfalse)これが!!uniq [obj.id]。uniqに既にidプロパティがある場合、trueを返し、評価はfalse(!)になり、フィルター関数にそのobjを追加しないように指示します。ただし、obj.idプロパティが見つからない場合、falseが返され、true(!)と評価され、&&または(uniq [obj.id] = true)の右側にあるすべてが返されます。これは真の値であり、フィルターメソッドに返された配列にそのobjを追加するように指示します。また、プロパティ{1:true}をuniqに追加します。これにより、同じIDを持つ他のobjインスタンスが再び追加されることがなくなります。


多分あなたのコードを説明し、それがどのように質問に答えるか?
mix3d 2018

ありがとう、mix3d。説明を追加しました。
MarkN 2018

説明してくれてありがとう!この解決策は私にとってはうまくいき、ここに投稿された他のいくつかの解決策と似ていますが、何が起こっているのか理解できませんでした:)
Tim Molloy

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

9
今後の訪問者があなたが何をしているかを理解できるように、コードの周りに説明を追加してください。ありがとう。
バグ

あなたの答えは外部コードライブラリに依存します...
テイラーA.リーチ

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マジックを1行で...読みやすい!

// 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)

このように、現在の要素を配列内の前の要素と比較するだけで済みます。フィルタリング前に1回ソートする(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"
}]

このソリューションは静的配列から重複を取り除くように設計されていますが、バックエンドからデータ配列にデータをプッシュする場合は、置換の使用を検討してください。この場合、データ配列にプッシュされた新しい値は削除され、「古い」値は引き続きデータ配列に格納されます。
ジュラジ2018

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はオブジェクトの配列です。同じ値を持つオブジェクトが存在します(ここでの小さな例では、2と同じitem_idを持つ2つのオブジェクトがあります)。check(id)は、同じitem_idを持つオブジェクトが存在するかどうかをチェックする関数です。存在する場合はfalseを返し、そうでない場合はtrueを返します。その結果に従って、オブジェクトを新しい配列objにプッシュします。 上記のコードの出力は [{"item_id":1},{"item_id":2}]


説明を追加
Mathews Sunny

@Billa大丈夫ですか?
Bibin Jaimon、2018年

1

ロダッシュ図書館をご存知ですか?ロジックをコードに適用したくない場合は、このユーティリティをお勧めします。最適化された信頼性の高い既存のコードを使用します。

このような配列を作ることを検討してください

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"});

1つの属性を一意にしたい場合は、lodashライブラリを使用すると非常にうまくいくことに注意してください。ここでは、_。uniqByを使用できます

.uniqBy(array、[iteratee = .identity])

このメソッドは_.uniq(重複のないバージョンの配列を返し、各要素の最初の出現のみが保持される)に似ていますが、配列の各要素に対して呼び出されるiterateeを受け入れ、一意性が計算されます。

したがって、たとえば、 'place'の一意の属性を持つ配列を返したい場合

_.uniqBy(things.thing、 '場所')

同様に、「名前」として一意の属性が必要な場合

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

お役に立てれば。

乾杯!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.