我有一个看起来像这样的对象数组:
[
{
"places": "NEW YORK",
"locations": "USA"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
}
]
我想过滤并仅获取唯一的条目。我尝试了以下功能,但不起作用:
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
使用Set
似乎也不起作用。有什么想法吗?
答案 0 :(得分:2)
使用new Set()
的简单解决方案。
const data = [
{
"places": "NEW YORK",
"locations": "USA"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
},
];
const uniqueArray = a => [...new Set(a.map(o => JSON.stringify(o)))].map(s => JSON.parse(s));
console.log(uniqueArray(data));
答案 1 :(得分:0)
您可以这样做
let data = data.filter(function (a) {
let key = a.places + '|' + a.country;
if (!this[key]) {
this[key] = true;
return true;
}
}, Object.create(null));
console.log(data);
答案 2 :(得分:0)
如果您使用下划线,则可以这样:
var list = [
{
"places": "NEW YORK",
"locations": "USA"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
},
];
var uniqList = _.uniq(list, function (item) {
return item.places+'_'+item.locations+'_'+item.country;
});
console.log(uniqList);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
答案 3 :(得分:0)
您可以将filter
与本地Set
对象一起使用。通过比较试图加到size
前后的字符串化对象和Set
属性,可以通过询问两个数字是否相等来返回唯一数组。
place_array.filter(v => b.size != b.add(JSON.stringify(v)).size, b = new Set());
与许多其他答案不同,它依赖于使用过滤器迭代器对数组的单次传递。这意味着它比遍历一个数组的多次循环性能更高。它还仅使用局部变量,这意味着它们不是全局混乱的对象,并且由于filter
方法具有功能,因此绝对没有副作用。
注意: 在任何情况下使用Set
对象时,性能总是会受到影响。这归结于浏览器内部,但是在发现将stringify
转换为Set
方法的唯一对象/数组可能是最好的解决方案。尽管数据集非常少,但您可能会发现使用数组或构建自己的特定于任务的对象很实用。
let place_array = [{
"places": "NEW YORK",
"locations": "USA"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
},
];
let result = place_array.filter(v => b.size != b.add(JSON.stringify(v)).size, b = new Set());
console.log(result);
您可以将filter
与本地Array
对象一起使用。通过确定字符串对象是否已经在数组中并推送是否存在,可以通过询问字符串对象是否不包含在数组中来返回唯一数组。
place_array.filter(v => !b.includes(s(v)) && !!b.push(s(v)), s = JSON.stringify, b = []);
尽管Set
对象可能有效,但是由于后端处理的原因,它最终比使用Array
对象要慢。您可以通过运行类似jsperf的测试来轻松证明这一点:https://jsperf.com/set-vs-ray-includes-battle/1
let place_array = [{
"places": "NEW YORK",
"locations": "USA"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
},
];
let result = place_array.filter(v => !b.includes(s(v)) && !!b.push(s(v)), s = JSON.stringify, b = []);
console.log(result);
答案 4 :(得分:0)
类似这样的东西:
var distObj = {};
for(let i = 0; i < obj.places.lenght; i++){
let tmp = obj.places;
distObj[i].places = obj[i].places.filter(item => item !== tmp);
}
如果将其与for(Obj中的k)和回调结合使用,则可以遍历Object中的每个深层和attr
答案 5 :(得分:0)
如果键值像示例中那样简单,则可以执行以下操作来处理实例,其中数组中的对象具有相同的键和值,但顺序不同(自object property order is not guaranteed across browsers起)
Object.entries
将对象转换为数组,使用JSON.stringify
排序并转换为字符串Set
删除重复项,并使用JSON.parse
将字符串转换回数组,然后使用reduce
将字符串转换回对象,以将数组对转换为对象键值对
const arr = [{
"places": "NEW YORK",
"locations": "USA"
},
{
"places": "MONTREAL",
"locations": "QUEBEC",
"country": "Canada"
},
{
"country": "Canada",
"places": "MONTREAL",
"locations": "QUEBEC"
}
];
let strings = arr.map(obj => JSON.stringify(Object.entries(obj).sort()));
let result = [...new Set(strings)].map((s) => {
return JSON.parse(s).reduce((acc, [k, v]) => {
acc[k] = v;
return acc;
}, {});
});
console.log(result);
// [{"locations":"USA","places":"NEW YORK"},{"country":"Canada","locations":"QUEBEC","places":"MONTREAL"}]