JavaScript:删除共享相同属性值的对象的重复项

时间:2015-08-27 00:01:49

标签: javascript arrays angularjs object key-value

我有一系列对象,我想根据特定的key:value对修剪它们。我想创建一个数组,每个特定的key:value对只包含一个对象。将重复的哪个对象复制到新数组并不一定重要。

例如,我想根据price的{​​{1}}属性进行修剪,创建一个只包含每个值之一的新数组:

arrayWithDuplicates

会变成:

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

是否有JavaScript或Angular函数可以循环执行此操作?

  

编辑:要过滤的属性嵌套在另一个属性中。

11 个答案:

答案 0 :(得分:13)

我认为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"
    }
]

答案 1 :(得分:8)

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

答案 2 :(得分:4)

您可以使用underscore

{{1}}

答案 3 :(得分:3)

您可以使用 lodash 删除重复的对象:

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

id”是您的唯一标识符

答案 4 :(得分:1)

简单的解决方案虽然不是最高性能的:

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

答案 5 :(得分:1)

使用lodash您可以轻松过滤

第一个参数将是您的数组,第二个参数将是您的重复字段

_.uniqBy(arrayWithDuplicates, 'color')

它将返回一个具有唯一值的数组

答案 6 :(得分:1)

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

答案 7 :(得分:0)

当我处理一系列对象时,没有任何一个函数会为你做这件事,而且没有规则可以将副本作为重复删除。

在您的示例中,您删除了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的一些文献 如果您需要提供要删除的项目的首选项,您可以定义额外的参数和逻辑,以便在添加返回值之前进行额外的属性检查。

希望有所帮助!

答案 8 :(得分:0)

这是打字稿方式

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

答案 9 :(得分:0)

这只是基于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;
};

希望在基于单个对象属性值过滤掉对象时,即使不是所有数组,此方法也适用于大多数数组。

答案 10 :(得分:0)

尝试以下功能:

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