簡體   English   中英

JavaScript:刪除共享相同屬性值的對象的重復項

[英]JavaScript: Remove duplicates of objects sharing same property value

我有一組對象,我想根據特定的key:value對來修剪它們。 我想創建一個數組,其中每個特定key:value對只包含一個對象。 將副本的哪個對象復制到新數組並不一定重要。

例如,我想根據arrayWithDuplicatesprice屬性進行修剪,創建一個僅包含每個值之一的新數組:

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 函數可以循環執行此操作?

編輯:要過濾的屬性嵌套在另一個屬性中。

此函數通過返回一個新值從數組中刪除重復值。

 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; }); } var values = [{color: "red"}, {color: "blue"}, {color: "red", number: 2}]; var withoutDuplicates = removeDuplicatesBy(x => x.color, values); console.log(withoutDuplicates); // [{"color": "red"}, {"color": "blue"}]

所以你可以像這樣使用它

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

我認為 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"
    }
]

使用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;
    });
}

您可以為此使用下划線

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

//by custom.price;
var uPrice = _.uniqBy(arrayWithDuplicates, function(p){ return p.custom.price; });

您可以使用lodash刪除重復的對象:

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

這里' id '是你的唯一標識符

嘗試以下功能:

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

簡單的解決方案雖然不是最高效的:

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

使用lodash您可以輕松將其過濾掉

第一個參數將是您的數組,第二個參數將是您的重復字段

_.uniqBy(arrayWithDuplicates, 'color')

它將返回一個具有唯一值的數組

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

在我的腦海中,沒有一個函數可以為您執行此操作,因為您正在處理一組對象,並且沒有規則將重復項作為重復項刪除。

在您的示例中,您刪除了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'));

您可以在此處查看有關數組過濾的一些文獻如果您需要提供要刪除的項目的偏好,您可以定義額外的參數和邏輯,這些參數和邏輯將在添加到返回值之前進行額外的屬性檢查。

希望有幫助!

這是打字稿的方式

    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');

這只是基於 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;
};

當基於單個對象屬性值過濾掉對象時,希望這對大多數數組(如果不是所有數組)都有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM