web-dev-qa-db-ja.com

JavaScript:同じプロパティ値を共有するオブジェクトの重複を削除します

特定のkey:valueペアに基づいてトリムしたいオブジェクトの配列があります。この特定のkey:valueペアごとに1つのオブジェクトのみを含む配列を作成します。重複のどのオブジェクトが新しい配列にコピーされるかは必ずしも問題ではありません。

たとえば、pricearrayWithDuplicatesプロパティに基づいてトリムし、各値の1つのみを含む新しい配列を作成します。

var arrayWithDuplicates = [
  {"color":"red", 
    "size": "small",
    "custom": {
      "inStock": true,
      "price": 10
    }
  },
  {"color":"green", 
    "size": "small",
    "custom": {
      "inStock": true,
      "price": 30
    }
  },
  {"color":"blue", 
    "size": "medium",
    "custom": {
      "inStock": true,
      "price": 30
    }
  },
  {"color":"red", 
    "size": "large",
    "custom": {
      "inStock": true,
      "price": 20
    }
  }
];

になるでしょう:

var trimmedArray = [
  {"color":"red", 
    "size": "small",
    "custom": {
      "inStock": true,
      "price": 10
    }
  },
  {"color":"green", 
    "size": "small",
    "custom": {
      "inStock": true,
      "price": 30
    }
  },
  {"color":"red", 
    "size": "large",
    "custom": {
      "inStock": true,
      "price": 20
    }
  }
];

ループしてこれを行うJavaScriptまたはAngular関数はありますか?

編集:フィルタリングするプロパティは、別のプロパティ内にネストされています。

26
Lauren F

これには nderscore を使用できます。

//by size:
var uSize = _.uniq(arrayWithDuplicates, function(p){ return p.size; });

//by custom.price;
var uPrice = _.uniq(arrayWithDuplicates, function(p){ return p.custom.price; });
5
user3335966
function removeDuplicatesBy(keyFn, array) {
  var mySet = new Set();
  return array.filter(function(x) {
    var key = keyFn(x), isNew = !mySet.has(key);
    if (isNew) mySet.add(key);
    return isNew;
  });
}

使用法(EcmaScript6矢印関数により見栄えが良くなります):

removeDuplicatesBy(x => x.custom.price, yourArrayWithDuplicates);

編集:スニペットを編集してプロパティ名を使用せず、キーセレクター機能を使用して、ネストされたプロパティにアクセスできるようにしました。

26
Tamas Hegedus

Angularには組み込み関数はないと思いますが、作成するのは難しくありません。

function removeDuplicates(originalArray, objKey) {
  var trimmedArray = [];
  var values = [];
  var value;

  for(var i = 0; i < originalArray.length; i++) {
    value = originalArray[i][objKey];

    if(values.indexOf(value) === -1) {
      trimmedArray.Push(originalArray[i]);
      values.Push(value);
    }
  }

  return trimmedArray;

}

使用法:

removeDuplicates(arrayWithDuplicates, 'size');

戻り値:

[
    {
        "color": "red",
        "size": "small"
    },
    {
        "color": "blue",
        "size": "medium"
    },
    {
        "color": "red",
        "size": "large"
    }
]

そして

removeDuplicates(arrayWithDuplicates, 'color');

戻り値:

[
    {
        "color": "red",
        "size": "small"
    },
    {
        "color": "green",
        "size": "small"
    },
    {
        "color": "blue",
        "size": "medium"
    }
]
12
yvesmancera

Array.filter()を使用し、Objectをハッシュとして使用して値を追跡し、値が既にハッシュに含まれているアイテムをすべて除外します。

function trim(arr, key) {
    var values = {};
    return arr.filter(function(item){
        var val = item[key];
        var exists = values[val];
        values[val] = true;
        return !exists;
    });
}
8
gilly3

lodashを使用して、重複するオブジェクトを削除できます。

 import * as _ from 'lodash';
  _.uniqBy(data, 'id');

ここで、「id」は一意の識別子です

3
Mukesh Ranjan
for (let i = 0; i < arrayWithDuplicates.length; i++) {
     for (let j = i + 1; j < arrayWithDuplicates.length; j++) {
       if (arrayWithDuplicates[i].name === students[j].name) {
          arrayWithDuplicates.splice(i, 1);
       }
     }
    }

this will work perfectly...and this will delete first repeated array.
To delete last repeated array we only have to change
 arrayWithDuplicates.splice(i, 1) ; into
 arrayWithDuplicates.splice(j, 1);
1
sudha priya

最も簡単なソリューションですが、最もパフォーマンスの高いものではありません。

var unique = [];
duplicates.forEach(function(d) {
    var found = false;
    unique.forEach(function(u) {
        if(u.key == d.key) {
            found = true;
        }
    });
    if(!found) {
        unique.Push(d);
    }
});
1
Souvik Basu

lodashを使用すると、簡単にフィルタリングできます

最初のパラメーターは配列で、2番目のパラメーターは重複するフィールドです

_.uniqBy(arrayWithDuplicates, 'color')

一意の値を持つ配列を返します

1
yureka

次の機能を試してください。

function trim(items){
    const ids = [];
    return items.filter(item => ids.includes(item.id) ? false : ids.Push(item.id));
}
0
sliter

私の頭上には、オブジェクトの配列を扱っているため、これを行う機能はありません。また、重複として重複を削除するルールもありません。

あなたの例では、size: smallしかし、ループを使用してこれを実装する場合、配列をループするときに最初の行を含め、最後の行を除外する可能性が高いでしょう。

lodash などのライブラリを見て、そのAPIメソッドの組み合わせを使用して目的の動作を実現する関数を作成することは非常に価値があります。

基本的な配列とフィルター式を利用して、返される結果に添付される前に新しいアイテムが複製と見なされるかどうかを確認するために使用できる解決策を次に示します。

var arrayWithDuplicates = [
    {"color":"red", "size": "small"},
    {"color":"green", "size": "small"},
    {"color":"blue", "size": "medium"},
    {"color":"red", "size": "large"}
];

var reduce = function(arr, prop) {
  var result = [],
      filterVal,
      filters,
      filterByVal = function(n) {
          if (n[prop] === filterVal) return true;
      };
  for (var i = 0; i < arr.length; i++) {
      filterVal = arr[i][prop];
      filters   = result.filter(filterByVal);
      if (filters.length === 0) result.Push(arr[i]);
  }
  return result;
};

console.info(reduce(arrayWithDuplicates, 'color'));

配列フィルタリングに関するいくつかの文献を確認できます here 削除する項目の設定を提供する必要がある場合は、戻り値に追加する前に追加のプロパティチェックを行う追加のパラメーターとロジックを定義できます。

お役に立てば幸いです!

0
jh3y

ここにTypeScriptの方法があります

    public removeDuplicates(originalArray:any[], prop) {
    let newArray = [];
    let lookupObject = {};

    originalArray.forEach((item, index) => {
        lookupObject[originalArray[index][prop]] = originalArray[index];
    });

    Object.keys(lookupObject).forEach(element => {
        newArray.Push(lookupObject[element]);
    });
    return newArray;
}

そして

let output = this.removeDuplicates(yourArray,'color');
0
Praveen M P

これは、yvesmanceraのソリューションに基づいた別の「機能」です(自分のソリューションをいじり始めた後)また、現在使用できるのはIE 11のみであるため、制限されたES5が許可されています。

var newArray = RemoveDuplicates(myArray,'Role', 2);

function RemoveDuplicates(array, objKey, rtnType) {
var list = [], values = [], value;
for (var i = 0; i < array.length; i++) {
    value = array[i][objKey];
    if(values.indexOf(value) === -1){
        list.Push(array[i]);
        values.Push(value);
        }
    }
    if(rtnType == 1)
        return list;
    return values;
};

単一のオブジェクトプロパティ値に基づいてオブジェクトをフィルタリングするときに、すべてではないにしても、ほとんどの場合、これが機能することを願っています。

0
Keltanis