根据对象的键和值合并对象



我已经编辑了原始问题,因为该示例没有明确所需的输出,即我没有指定我需要与与Rank匹配的对象通用的字符串

我正在尝试将一个对象数组合并为一个对象

object有三组keys,我希望每组只有一个实例,其Rank值的最小数字,或者如果Rank在所有对象上等于"-"。

let objs = [
{
Keyword: 'A keyword',
'First Rank': '-',
'First Title': '-',
'First URL': '-',
'Second Rank': '-',
'Second Title': '-',
'Second URL': '-',
'Third Rank': 1,
'Third Title': 'Title for 1',
'Third URL': 'https://for-one.example.com'
},
{
Keyword: 'A keyword',
'First Rank': '-',
'First Title': '-',
'First URL': '-',
'Second Rank': 2,
'Second Title': 'Title for 2',
'Second URL': 'https://for-two.example.com',
'Third Rank': '-',
'Third Title': '-',
'Third URL': '-'
},
{
Keyword: 'A keyword',
'First Rank': '-',
'First Title': '-',
'First URL': '-',
'Second Rank': '-',
'Second Title': '-',
'Second URL': '-',
'Third Rank': 7,
'Third Title': 'Title for 7',
'Third URL': 'https://for-seven.example.com'
}
]
// I have managed to get the ones with values with this:
const clean = objs.reduce((acc, object) => {
const clone = (({ Keyword, ...obj }) => obj)(object)
if (Object.values(clone).some(val => val !== '-')) {
Object.keys(clone).forEach(key => object[key] === '-' && delete object[key])
acc.push(object)
}
return acc
}, [])
const merged = clean.reduce((result, current) => ({ ...current, ...result }), {})
console.log(merged)

但是我正在努力添加没有值的那个,它应该看起来像这样:

{
'Keyword': 'A keyword',
'First Rank': '-',
'First Title': '-',
'First URL': '-',
'Second Rank': 2,
'Second Title': 'Title for 2',
'Second URL': 'https://for-two.example.com',
'Third Rank': 1,
'Third Title': 'Title for 1',
'Third URL': 'https://for-one.example.com'
}

有什么想法吗?谢谢!

试试这个

let objs = [
{
'Keyword': 'A keyword',
'First URL': '-',
'First Rank': '-',
'First Title': '-',
'Second URL': '-',
'Second Rank': '-',
'Second Title': '-',
'Third URL': '-',
'Third Rank': '-',
'Third Title': '-'
},
{
'Keyword': 'A keyword',
'First URL': '-',
'First Rank': '-',
'First Title': '-',
'Second URL': '-',
'Second Rank': '-',
'Second Title': '-',
'Third URL': 'https://example.com',
'Third Rank': 7,
'Third Title': 'Title'
},
{
'Keyword': 'A keyword',
'First URL': '-',
'First Rank': '-',
'First Title': '-',
'Second URL': 'https://example.com',
'Second Rank': 11,
'Second Title': 'Title',
'Third URL': '-',
'Third Rank': '-',
'Third Title': '-'
},
{
'Keyword': 'A keyword',
'First URL': '-',
'First Rank': '-',
'First Title': '-',
'Second URL': '-',
'Second Rank': '-',
'Second Title': '-',
'Third URL': 'https://example.com',
'Third Rank': 1,
'Third Title': 'Title overwritten'
},
]
var result = objs.slice().reduce((acc, item, index) => {
resultItem = acc.find(accItem => accItem['Keyword'] === item['Keyword']);
if (!resultItem) {
acc.push(item)
} else {
Object.keys(resultItem).map(k => {
if (item[k] !== '-') {
if (typeof item[k] === 'number') {
resultItem[k] = resultItem[k] === '-' ? item[k] : Math.min(item[k], resultItem[k]);
} else {
resultItem[k] = item[k];
}
}
})
}
return acc;  
}, []);
console.log(result);

您可以减少并在处理程序中检查数字值,以便比较两个值之间的最小值。

在此代码片段中,还有一个附加对象具有Third Rank = 1

let array = [{ Keyword: 'A keyword', 'First URL': '-', 'First Rank': '-', 'First Title': '-', 'Second URL': '-', 'Second Rank': '-', 'Second Title': '-', 'Third URL': '-', 'Third Rank': '-', 'Third Title': '-' }, { Keyword: 'A keyword', 'First URL': '-', 'First Rank': '-', 'First Title': '-', 'Second URL': '-', 'Second Rank': '-', 'Second Title': '-', 'Third URL': 'https://example.com', 'Third Rank': 7, 'Third Title': '2 third title' }, { Keyword: 'A keyword', 'First URL': '-', 'First Rank': '-', 'First Title': '-', 'Second URL': 'https://example.com', 'Second Rank': 11, 'Second Title': '3 Second title', 'Third URL': '-', 'Third Rank': '-', 'Third Title': '-' }, { Keyword: 'A keyword', 'First URL': '-', 'First Rank': '-', 'First Title': '-', 'Second URL': 'https://example.com', 'Second Rank': 11, 'Second Title': '3 Second title', 'Third URL': '-', 'Third Rank': 1, 'Third Title': '-' }],
merged = array.reduce(({ ...r }, o) => {
Object.entries(o).forEach(([k, v]) => {
if (v !== '-') {
if (isNaN(+v) || isNaN(+r[k])) r[k] = v;
else r[k] = Math.min(+r[k], +v);
}
});
return r;
});

console.log(merged);

您可以缩小数组并检查条目的键。

let array = [{ 'Keyword': 'A keyword', 'First URL': '-', 'First Rank': '-', 'First Title': '-', 'Second URL': '-', 'Second Rank': '-', 'Second Title': '-', 'Third URL': '-', 'Third Rank': '-', 'Third Title': '-' }, { 'Keyword': 'A keyword', 'First URL': '-', 'First Rank': '-', 'First Title': '-', 'Second URL': '-', 'Second Rank': '-', 'Second Title': '-', 'Third URL': 'https://for-seven.example.com', 'Third Rank': 7, 'Third Title': 'Title' }, { 'Keyword': 'A keyword', 'First URL': '-', 'First Rank': '-', 'First Title': '-', 'Second URL': 'https://for-eleven.example.com', 'Second Rank': 11, 'Second Title': 'Title', 'Third URL': '-', 'Third Rank': '-', 'Third Title': '-' }, { 'Keyword': 'A keyword', 'First URL': '-', 'First Rank': '-', 'First Title': '-', 'Second URL': '-', 'Second Rank': '-', 'Second Title': '-', 'Third URL': 'https://for-one.example.com', 'Third Rank': 1, 'Third Title': 'Title' }],
merged = array.reduce(({ ...r }, o) => {
var prefix = ['First', 'Second', 'Third'].find(k => o[k + ' Rank'] !== '-'),
rank = prefix + ' Rank';
if (r[rank] < o[rank]) return;
['URL', 'Rank', 'Title'].forEach(k => {
var key = `${prefix} ${k}`
r[key] = o[key];
});
return r;
});

console.log(merged);
.as-console-wrapper { max-height: 100% !important; top: 0; }

感谢所有回答这个问题的人,但是我没有详细解释一些要求,当我这样做时,为时已晚,无法得到后续回复,所以我自己做了,我相信有更好的方法可以做到这一点,但这有效。

let objs = [
{
'Keyword': 'A keyword',
'First Rank': '-',
'First Title': '-',
'First URL': '-',
'Second Rank': '-',
'Second Title': '-',
'Second URL': '-',
'Third Rank': 1,
'Third Title': 'Title for 1',
'Third URL': 'https://for-one.example.com'
},
{
'Keyword': 'A keyword',
'First Rank': '-',
'First Title': '-',
'First URL': '-',
'Second Rank': 2,
'Second Title': 'Title for 2',
'Second URL': 'https://for-two.example.com',
'Third Rank': '-',
'Third Title': '-',
'Third URL': '-'
},
{
'Keyword': 'A keyword',
'First Rank': '-',
'First Title': '-',
'First URL': '-',
'Second Rank': '-',
'Second Title': '-',
'Second URL': '-',
'Third Rank': 7,
'Third Title': 'Title for 7',
'Third URL': 'https://for-seven.example.com'
}
]
// Remove dashed entries and keep only the ones with data
const removeDashed = objs.reduce((acc, object) => {
// Clone object except for the keyword key
const clone = (({ Keyword, ...obj }) => obj)(object)
if (Object.values(clone).some(val => val !== '-')) {
Object.keys(object).forEach(key => object[key] === '-' && delete object[key])
acc.push(object)
}
return acc
}, [])
// Merge array into a single object with first entries found first
const merged = removeDashed.reduce((result, current) => ({ ...current, ...result }), {})
// Items that should be present
const items = ['First', 'Second', 'Third']
// Get the existing keys from the unique obj
const keys = Object.keys(merged).map(key => key.split(' ')[0])
// If one or more items are missing insert them and add dashed values
items.forEach(item => {
if (!keys.includes(item)) {
merged[`${item} Rank`] = '-'
merged[`${item} Title`] = '-'
merged[`${item} URL`] = '-'
}
})
// Sort function to reorder | thanks to Soc for this
const sorting = item => (a, b) => {
const alphaOrder = a < b ? -1 : a > b ? 1 : 0
if (a === 'Keyword') return -1
if (b === 'Keyword') return 1
if (a.startsWith(item) && b.startsWith(item)) return alphaOrder
if (a.startsWith(item)) return -1
if (b.startsWith(item)) return 1
return alphaOrder
}
// Implement the sorting
const result = Object.keys(merged)
.sort(sorting(items[0]))
.reduce((acc, current) => {
acc[current] = merged[current]
return acc
}, {})
console.log(result)

最新更新