【发布时间】:2013-12-23 08:23:59
【问题描述】:
我有一个对象数组,我想从中获取一个新数组,该数组仅基于单个属性是唯一的,有没有简单的方法来实现这一点?
例如。
[ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
将导致 2 个名称 = bill 的对象被删除一次。
【问题讨论】:
我有一个对象数组,我想从中获取一个新数组,该数组仅基于单个属性是唯一的,有没有简单的方法来实现这一点?
例如。
[ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
将导致 2 个名称 = bill 的对象被删除一次。
【问题讨论】:
使用uniq 函数
var destArray = _.uniq(sourceArray, function(x){
return x.name;
});
或单行版本
var destArray = _.uniq(sourceArray, x => x.name);
来自文档:
生成数组的无重复版本,使用 === 来测试对象是否相等。如果您事先知道数组已排序,则为 isSorted 传递 true 将运行更快的算法。如果您想根据转换计算唯一项,请传递一个迭代器函数。
在上面的示例中,函数使用对象名称来确定唯一性。
【讨论】:
如果您更喜欢在不使用 Lodash 且不冗长的情况下自己做事,请尝试使用可选 uniq by property 的 uniq 过滤器:
const uniqFilterAccordingToProp = function (prop) {
if (prop)
return (ele, i, arr) => arr.map(ele => ele[prop]).indexOf(ele[prop]) === i
else
return (ele, i, arr) => arr.indexOf(ele) === i
}
然后,像这样使用它:
const obj = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
obj.filter(uniqFilterAccordingToProp('abc'))
或者对于普通数组,只需省略参数,同时记住调用:
[1,1,2].filter(uniqFilterAccordingToProp())
【讨论】:
如果您想检查所有属性,那么 lodash 4 自带 _.uniqWith(sourceArray, _.isEqual)
【讨论】:
更好更快捷的方法
var table = [
{
a:1,
b:2
},
{
a:2,
b:3
},
{
a:1,
b:4
}
];
let result = [...new Set(table.map(item => item.a))];
document.write(JSON.stringify(result));
【讨论】:
a 的唯一值,而我们应该获取 table 的所有具有唯一 a 属性的子级。结果的差异是[1, 2](当前)与[{ a: 1, b: 2 }, { a: 2, b: 3 }](预期)。
你可以使用_.uniqBy函数
var array = [ { id: 1, name: 'bob' }, { id: 2, name: 'bill' }, { id: 1, name: 'bill' },{ id: 2, name: 'bill' } ];
var filteredArray = _.uniqBy(array,function(x){ return x.id && x.name;});
console.log(filteredArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
在上面的例子中,过滤是基于属性 id 和 name 组合的唯一性。
如果一个对象有多个属性。 然后要根据特定属性找到唯一的对象数组,您可以按照这种在 _.uniqBy() 方法中组合属性的方法。
【讨论】:
${x.name}/{x.id};
name 是独一无二的。 x.id 总是!falsy,所以你的回报就是x.name。如果您想要 2 个属性的唯一性,那么 id: 1, name: bill 应该在结果中。它不是。尝试使用 return `${x.id}/${x.name]` 你会明白我的意思。
我正在寻找一个不需要库的解决方案,并将它放在一起,所以我想我会在这里添加它。它可能并不理想,或者在所有情况下都有效,但它正在满足我的要求,因此可能会帮助其他人:
const uniqueBy = (items, reducer, dupeCheck = [], currentResults = []) => {
if (!items || items.length === 0) return currentResults;
const thisValue = reducer(items[0]);
const resultsToPass = dupeCheck.indexOf(thisValue) === -1 ?
[...currentResults, items[0]] : currentResults;
return uniqueBy(
items.slice(1),
reducer,
[...dupeCheck, thisValue],
resultsToPass,
);
}
const testData = [
{text: 'hello', image: 'yes'},
{text: 'he'},
{text: 'hello'},
{text: 'hell'},
{text: 'hello'},
{text: 'hellop'},
];
const results = uniqueBy(
testData,
item => {
return item.text
},
)
console.dir(results)
【讨论】:
Set 据我所知,您无法选择以编程方式确定唯一性
如果您需要纯 JavaScript 解决方案:
var uniqueProperties = {};
var notUniqueArray = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ];
for(var object in notUniqueArray){
uniqueProperties[notUniqueArray[object]['name']] = notUniqueArray[object]['id'];
}
var uniqiueArray = [];
for(var uniqueName in uniqueProperties){
uniqiueArray.push(
{id:uniqueProperties[uniqueName],name:uniqueName});
}
//uniqiueArray
【讨论】:
使用 ES6 的 id 属性的唯一数组:
arr.filter((a, i) => arr.findIndex(b => b.id === a.id) === i); // unique by id
将b.id === a.id替换为您的案例的相关比较
【讨论】: