获取具有重复值的数组中的对象

时间:2017-10-15 14:36:47

标签: javascript arrays

我需要从一个对象数组中获取元素,其中一个对象的属性(在这种情况下为name)是重复的 - 换句话说,出现在数组中的某个其他对象中。

数据

var data = [
  {id:1, name:"sam", userid:"ACD"},
  {id:1, name:"ram", userid:"SDC"},
  {id:1, name:"sam", userid:"CSTR"}
];

我需要检查所有行并获取name属性重复的所有数组值。

预期产出:

[
  {id:1, name:"sam", userid:"ACD"},
  {id:1, name:"sam", userid:"CSTR"}
]

我的代码

Array.from(data).map(x => x.name)

但它会返回所有值。

代码不应该产生任何性能问题,因为数组将包含超过500行。

2 个答案:

答案 0 :(得分:0)

Angular是一个框架,而不是一种语言。你的问题中没有 Angular

让我理解,如果我理解得很好。你有一个对象数组,你想保留所有重复的元素并摆脱其他元素,好吧?你可以尝试:

data.reduce((acc, value, i, arr) => {
  if(acc.some(v => v.name === value.name)) return acc;
  let filtered = arr.filter(v => v.name === value.name);
  return filtered.length > 1 ? acc.concat(filtered) : acc;
}, []);

或者您可以在第一个实例中对数组进行排序,以提高性能:

const sort = (a, b) => a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1;

let duplicates = [];

let sortedArray = data.sort(sort);

for(let i=0; i<sortedArray.length - 1; i++) {
  if(sortedArray[i].name === sortedArray[i+1].name) {
    duplicates.push(sortedArray[i], sortedArray[i+1]);
    i++;
  }
}

答案 1 :(得分:0)

蛮力方法是过滤数组以仅保留具有重复名称的元素,如过滤函数duplicateName所表示。

// Is there more than one element in an array satisfying some predicate?
const hasMultiple = (arr, pred) => arr.filter(pred).length > 1;

// Is this element a duplicate in the context of the array?
const duplicateName = (elt, idx, arr) => hasMultiple(arr, e => e.name === elt.name);

// Test data.
var data = [
  {id:1,name:"sam", userid:"ACD"},
  {id:1,name:"ram", userid:"SDC"},
  {id:1,name:"sam", userid:"CSTR"}
];
   
console.log(data.filter(duplicateName));

但是,在许多元素的情况下,这将导致性能不佳(O(n^2))。要解决该问题,您需要预处理该数组。我们将为每个名称创建一个具有属性的对象,其值是该名称出现的所有元素的数组。此操作通常称为groupBy。几个流行的库,如下划线将为您提供此功能。我们会写自己的。分组后,我们将过滤组的对象以删除只有一个成员的对象。

// Group an array by some predicate.
const groupBy = (arr, pred) => arr.reduce((ret, elt) => {
    const val = pred(elt);
    (ret[val] = ret[val] || []).push(elt);
    return ret;
  }, {});
  
// Filter an object, based on a boolean callback.
const filter = (obj, callback) => Object.keys(obj).reduce((res, key) => {
    if (callback(obj[key], key, obj)) res[key] = obj[key];
    return res;
  }, {});

// Remove groups with only one element.
const removeNonDups = groups => filter(groups, group => group.length > 1);

// Test data.
var data = [
  {id:1,name:"sam", userid:"ACD"},
  {id:1,name:"ram", userid:"SDC"},
  {id:1,name:"sam", userid:"CSTR"}
];

console.log(removeNonDups(groupBy(data, elt => elt.name)));

相关问题