我有一个这样的对象数组:
// other properties of the object omitted for brevity
// this array can potentially contain upto 50 objects like this
var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
我正在尝试应用reduce函数来创建一个像这样的新对象:
var newArray = myArray.reduce(function(acc, current, index){
var newObj = {};
newObj['strata'] = 'kit';
newObj['href'] = current['url'];
acc.push(newObj);
return acc;
}, [])
但是我不想包含重复的对象(使用对象的'url'属性测试的'duplicate')。如何修改我的reduce函数以跳过此类对象并产生
[{strata: kit, href: 'http://linkA'}, {strata: kit, href: 'http://linkB'}]
编辑:抱歉,我忘了提到这是旧代码。我无法使用“设置”和“某些”等功能
答案 0 :(得分:2)
使用some
:
var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}];
var newArray = myArray.reduce(function(acc, { url }, index) {
if (Object.values(acc).some(({ href }) => href === url)) {
return acc;
}
acc.push({
strata: 'kit',
href: url
});
return acc;
}, [])
console.log(newArray);
答案 1 :(得分:1)
您可以先检查url
是否在累加器的任何对象中存在:
var myArray = [{
url: 'http://linkA'
}, {
url: 'http://linkB'
}, {
url: 'http://linkA'
}];
var newArray = myArray.reduce(function(acc, { url }, index) {
if (acc.some(obj => obj.href === url)) {
return acc;
}
acc.push({
strata: 'kit',
href: url
});
return acc;
}, [])
console.log(newArray);
要使O(N)
而不是O(N^2)
复杂,请将每个URL添加到外部Set
(其查找是O(1)
,而不是{{1}的O(N)
}}):
Array.prototype.some
或者,在ES5中,使用对象代替Set:
var myArray = [{
url: 'http://linkA'
}, {
url: 'http://linkB'
}, {
url: 'http://linkA'
}];
const urls = new Set();
var newArray = myArray.reduce(function(acc, { url }, index) {
if (urls.has(url)) {
return acc;
}
urls.add(url);
acc.push({
strata: 'kit',
href: url
});
return acc;
}, [])
console.log(newArray);
答案 2 :(得分:1)
您可以在some()
之前使用push()
检查重复项
var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
var newArray = myArray.reduce(function(acc, current, index){
var newObj = {};
newObj['strata'] = 'kit';
newObj['href'] = current['url'];
if(!acc.some(x => x.href === current.url)) acc.push(newObj);
return acc;
}, [])
console.log(newArray)
较短的代码将是
var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
const res= myArray.reduce((ac,a) =>
(!ac.some(x => x.href === a.url) &&
ac.push({strata:'kit',href:a.url}),
ac),
[]);
console.log(res)
答案 3 :(得分:1)
您可以先使用Set
获得所有唯一的url
。然后使用map
和Shorthand property names创建对象:
const myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}],
uniqueUrls = new Set(myArray.map(a => a.url)),
strata = "kit",
output = [...uniqueUrls].map(href => ({ strata, href }));
console.log(output)
如果您不能使用ES2015 +功能,则可以将一个对象作为累加器,并将每个唯一的url
作为键。这样,您在累加器中只会得到一个url
。然后遍历该对象并获取合并对象的值
var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}];
var merged = myArray.reduce(function(acc, current) {
acc[current.url] = current;
return acc;
}, {})
var output = [];
for(var key in merged) {
output.push(merged[key])
}
console.log(output)
这是合并对象的样子:
{
"http://linkA": {
"url": "http://linkA"
},
"http://linkB": {
"url": "http://linkB"
}
}
答案 4 :(得分:0)
创建一个Set
,该数组仅接受URL中的URL映射到您的数组-Set将对您的数组进行重复数据删除,然后您可以使用strata
从Set中创建一个新数组属性添加到其中。
const myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
const s = new Set(myArray.map(({ url }) => url))
const newArray = [...s].map(url => ({
url,
strata: 'kit'
}))
console.log(newArray)
如果您希望最终的对象数组更加动态。创建一个函数,该函数将要删除重复数据的参数以及要插入最终对象的参数。
const DE_DUPE_INSERT = (array, flag, insert) => {
const s = new Set(array.map(item => item[flag]))
return [...s].map(property => ({
[flag]: property,
...insert
}))
}
const ARR = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
const de_duped = DE_DUPE_INSERT(ARR, 'url', {strata: 'kit', foo: 'bar'})
console.log(de_duped)
< es6
var DE_DUPE_INSERT = function (array, flag, insert) {
var de_duped = []
array.forEach(function (item) {
if (de_duped.indexOf(item[flag]) === -1) de_duped.push(item[flag])
})
return de_duped.map(function (property) {
var obj = {}
obj[flag] = property
Object.keys(insert).forEach(function (key) {
obj[key] = insert[key]
})
return obj
})
}
var ARR = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
var de_duped = DE_DUPE_INSERT(ARR, 'url', {strata: 'kit', foo: 'bar'})
console.log(de_duped)
答案 5 :(得分:0)
我可能会
Set
(或对象)跟踪我已经看到的URL,并且reduce
但这是仍使用reduce
的版本:
var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
var known = new Set();
var newArray = myArray.reduce(function(acc, current, index){
if (!known.has(current.url)) {
acc.push({
strata: 'kit',
href: current.url
});
known.add(current.url);
}
return acc;
}, [])
console.log(newArray);
这是使用循环的更简单的版本:
var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
var known = new Set();
var newArray = [];
for (const current of myArray) {
if (!known.has(current.url)) {
newArray.push({
strata: 'kit',
href: current.url
});
known.add(current.url);
}
}
console.log(newArray);
如果您无法使用Set
和for-of
之类的ES2015 +功能,则可以使用对象来跟踪URL和简单的for
循环:
var myArray = [{url: 'http://linkA'}, {url: 'http://linkB'}, {url: 'http://linkA'}]
var known = Object.create(null); // An object with no prototype
var newArray = [];
for (var index = 0; index < myArray.length; ++index) {
var current = myArray[index];
if (!known[current.url]) {
newArray.push({
strata: 'kit',
href: current.url
});
known[current.url] = true;
}
}
console.log(newArray);