我需要从一个对象数组中获取元素,其中一个对象的属性(在这种情况下为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行。
答案 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)));