我正在学习JS。假设我有以下对象数组:
var family = [
{
name: "Mike",
age: 10
},
{
name: "Matt"
age: 13
},
{
name: "Nancy",
age: 15
},
{
name: "Adam",
age: 22
},
{
name: "Jenny",
age: 85
},
{
name: "Nancy",
age: 2
},
{
name: "Carl",
age: 40
}
];
请注意, Nancy 会出现两次(仅更改年龄)。假设我只想输出唯一的名称。如何输出上面的对象数组,没有重复? ES6回答非常欢迎。
相关(无法找到在对象上使用的好方法):
编辑以下是我的尝试。它适用于字符串,但我无法弄清楚如何使它与对象一起使用:
family.reduce((a, b) => {
if (a.indexOf(b) < 0 ) {
a.push(b);
}
return a;
},[]);
答案 0 :(得分:23)
您可以在一行中将Set
与Array#map
和spread operator class YourNavigationController: UINavigationController {
override func childViewControllerForStatusBarStyle() -> UIViewController? {
return topViewController
}
}
结合使用。
Map返回一个包含所有名称的数组,这些数组将进入set初始化程序,然后该数组的所有值都以数组形式返回。
...
&#13;
要过滤并仅返回唯一名称,您可以将Array#filter
与Set
一起使用。
var family = [{ name: "Mike", age: 10 }, { name: "Matt", age: 13 }, { name: "Nancy", age: 15 }, { name: "Adam", age: 22 }, { name: "Jenny", age: 85 }, { name: "Nancy", age: 2 }, { name: "Carl", age: 40 }],
unique = [...new Set(family.map(a => a.name))];
console.log(unique);
&#13;
答案 1 :(得分:10)
在对象中存储循环外部name
的出现次数,并在先前出现的情况下进行过滤。
https://jsfiddle.net/nputptbb/2/
var occurrences = {}
var filteredFamily = family.filter(function(x) {
if (occurrences[x.name]) {
return false;
}
occurrences[x.name] = true;
return true;
})
您也可以将此解决方案概括为函数
function filterByProperty(array, propertyName) {
var occurrences = {}
return array.filter(function(x) {
var property = x[propertyName]
if (occurrences[property]) {
return false;
}
occurrences[property]] = true;
return true;
})
}
并像
一样使用它var filteredFamily = filterByProperty(family, 'name')
不要使用indexOf
比较对象,===
仅在对象之间使用===
运算符。你当前的答案不起作用的原因是因为JS中的var a = { x: 1 }
var b = { x: 1 }
console.log(a === b) // false
console.log(a === a) // true
没有深入比较对象,而是比较了引用。我的意思是你可以在下面的代码中看到:
name
Equality将告诉您是否找到完全相同的对象,但如果找到具有相同内容的对象则不会。
在这种情况下,您可以比较obj.name === obj.name
上的对象,因为它应该是唯一键。所以obj === obj
代替indexOf
。此外,您的代码影响其运行时而不是其功能的另一个问题是您在reduce
内部使用indexOf
。 O(n)
为O(n^2)
,这会使您的算法O(1)
变得复杂。因此,最好使用具有rails generate model order
查找的对象。
答案 2 :(得分:3)
这可以正常工作。
[1, 2, 2, 3, 3, 3, 3].reduce((x, y) => x.includes(y) ? x : [...x, y], [])
答案 3 :(得分:0)
使用您提到的代码,您可以尝试:
family.filter((item, index, array) => {
return array.map((mapItem) => mapItem['name']).indexOf(item['name']) === index
})
或者您可以使用通用函数使其适用于其他对象数组:
function printUniqueResults (arrayOfObj, key) {
return arrayOfObj.filter((item, index, array) => {
return array.map((mapItem) => mapItem[key]).indexOf(item[key]) === index
})
}
然后只使用printUniqueResults(family, 'name')
<强> (FIDDLE) 强>
答案 4 :(得分:0)
我刚刚想到了Lodash用户的2种简单方法
给出此数组:
let family = [
{
name: "Mike",
age: 10
},
{
name: "Matt",
age: 13
},
{
name: "Nancy",
age: 15
},
{
name: "Adam",
age: 22
},
{
name: "Jenny",
age: 85
},
{
name: "Nancy",
age: 2
},
{
name: "Carl",
age: 40
}
]
1。查找重复项:
let duplicatesArr = _.difference(family, _.uniqBy(family, 'name'), 'name')
// duplicatesArr:
// [{
// name: "Nancy",
// age: 2
// }]
2查找是否存在重复项,以进行验证:
let uniqArr = _.uniqBy(family, 'name')
if (uniqArr.length === family.length) {
// No duplicates
}
if (uniqArr.length !== family.length) {
// Has duplicates
}
答案 5 :(得分:0)
由于大多数答案不会有好的表现,我想我分享我对此的看法:
const arrayWithDuplicateData = [{ id: 5, name: 'Facebook'}, { id: 3, name: 'Twitter' }, { id: 5, name: 'Facebook' }];
const uniqueObj = {};
arrayWithDuplicateData.forEach(i => {
uniqueObj[i.id] = i;
});
const arrayWithoutDuplicates = Object.values(uniqueObj);
我们利用键在对象中是唯一的这一事实。这意味着第一个数组中的最后一个重复项将胜过它的前辈。如果我们想改变它,我们可以在迭代之前翻转数组。
此外,我们不必只使用对象的一个属性来识别重复项。
const arrayWithDuplicateData = [{ id: 5, name: 'Facebook'}, { id: 3, name: 'Twitter' }, { id: 5, name: 'Facebook' }];
const uniqueObj = {};
arrayWithDuplicateData.forEach(item => {
uniqueObj[`${item.id}_${item.name}`] = item;
});
const arrayWithoutDuplicates = Object.values(uniqueObj);
或者我们可以简单地添加一个检查,如果 uniqueObj 已经拥有一个键,如果是,则不要覆盖它。
总的来说,这种方式在性能方面成本并不高,到目前为止对我来说效果很好。
答案 6 :(得分:-1)
我可能会设置某种对象。由于您已经说过ECMAScript 6,因此您可以访问Set
,但由于您希望比较对象的值,因此需要花费更多的工作。
示例可能看起来像这样(为清晰起见,删除了命名空间模式):
var setOfValues = new Set();
var items = [];
function add(item, valueGetter) {
var value = valueGetter(item);
if (setOfValues.has(value))
return;
setOfValues.add(value);
items.push(item);
}
function addMany(items, valueGetter) {
items.forEach(item => add(item, valueGetter));
}
像这样使用:
var family = [
...
];
addMany(family, item => item.name);
// items will now contain the unique items
说明:您需要从每个对象中添加一个值,并根据您获得的值确定它是否已经添加。它需要一个值getter,它是一个给定项的函数,返回一个值(item => item.name
)。然后,您只需添加尚未看到其值的项目。
课程实施:
// Prevents duplicate objects from being added
class ObjectSet {
constructor(key) {
this.key = key;
this.items = [];
this.set = new Set();
}
add(item) {
if (this.set.has(item[this.key])) return;
this.set.add(item[this.key]);
this.items.push(item);
}
addMany(items) {
items.forEach(item => this.add(item));
}
}
var mySet = new ObjectSet('name');
mySet.addMany(family);
console.log(mySet.items);