我想从另一个对象数组创建一个对象数组以绘制图形。
这是我用来将对象位置放置在预期对象内的数组。
let uniqueSkills = ['Using', 'Analyzing', 'Summarizing', 'Inferring', 'Predicting', 'Activating']
这是我需要修改的对象。
let data = {
data0:[
{count: 1, length: 1, skill: "Activating"},
{count: 4, length: 1, skill: "Using"},
{count: 2, length: 1, skill: "Analyzing"}
],
data1: [
{count: 2, length: 1, skill: "Summarizing"}
],
data2: [
{count: 1, length: 1, skill: "Predicting"},
{count: 4, length: 1, skill: "Analyzing"}
]
}
最终结果对象应如下所示。
data = {
data0:[
{count: 4, length: 1, skill: "Using"},
{count: 2, length: 1, skill: "Analyzing"},
{skill: "Summarizing"},
{skill: "Inferring"},
{skill: "Predicting"},
{count: 4, length: 1, skill: "Activating"}
],
data1: [
{skill: "Using"},
{skill: "Analyzing"},
{count: 2, length: 1, skill: "Summarizing"},
{skill: "Inferring"},
{skill: "Predicting"},
{skill: "Activating"}
],
data2: [
{skill: "Using"},
{count: 4, length: 1, skill: "Analyzing"},
{skill: "Summarizing"},
{skill: "Inferring"},
{count: 1, length: 1, skill: "Predicting"},
{skill: "Activating"}
]
}
我编写的算法在某些情况下可以正常工作,但在某些情况下却可以中断。在这里,
Object.keys(data).forEach(key => {
for (let i = 0; i < uniqueSkills.length; i++) {
if (typeof data[key][i] == 'object') {
if (data[key][i].skill !== uniqueSkills[i]) {
let index = uniqueSkills.indexOf(data[key][i].skill)
if (typeof data[key][index] == 'object') {
let anotherIndex = uniqueSkills.indexOf(data[key][index].skill)
let elementAtIndex = data[key][index]
let elementAtAnotherIndex = data[key][anotherIndex]
data[key][i] = elementAtIndex
data[key][index] = elementAtAnotherIndex
}
else {
data[key][index] = data[key][i]
data[key][i] = {skill: uniqueSkills[i]}
}
}
} else {
data[key][i] = {skill: uniqueSkills[i]}
}
}
})
答案 0 :(得分:4)
您可以使用Map
首先创建一个空模板,对象中仅包含skill
属性,然后使用实际数据填充Map
。 Object.entries
和Object.fromEntries
可用于从普通对象到数组的转换,反之亦然。
由于Map
保留插入顺序,因此可以保证输出顺序。
let uniqueSkills = ['Using', 'Analyzing', 'Summarizing', 'Inferring', 'Predicting', 'Activating']
let data = {data0:[{count: 1, length: 1, skill: "Activating"},{count: 4, length: 1, skill: "Using"},{count: 2, length: 1, skill: "Analyzing"}],data1: [{count: 2, length: 1, skill: "Summarizing"}],data2: [{count: 1, length: 1, skill: "Predicting"},{count: 4, length: 1, skill: "Analyzing"}]};
let newData = Object.fromEntries(Object.entries(data).map(([k, arr]) =>
[k, Array.from(arr.reduce(
(map, o) => map.set(o.skill, o),
new Map(uniqueSkills.map(skill => [skill, { skill }]))
).values())]
));
console.log(newData);
请注意,此解决方案的时间复杂度为最差情况[em> O(n²)(以uniqueSkills
的长度表示)。您自己的解决方案的时间复杂度为 O(n³),其中有两个外部循环(forEach
和for
)和indexOf
的嵌套调用,代表一个循环。具有嵌套indexOf
或find
而不是findIndex
的其他解决方案,其时间复杂度也为 O(n³)。使用Map#get
而不是这些数组方法之一,可以将复杂度降低到 O(n²)。
此解决方案不会更改原始data
对象。它产生一个新对象。但是,新对象仍将包含在原始data
数组中找到的原始对象。
解决方案的问题是,您走过i
,index
,anotherIndex
的路径,试图移动一个妨碍您要插入的对象的对象。但是,这条路甚至可以更长。创建缺口,移动到下一个位置,在此处创建缺口等“步伐”是先验的,不受长度限制。
答案 1 :(得分:2)
对于数据中的每个对象,为Array.prototype.map
调用uniqueSkills
并找到一个对象。如果找到,则返回该对象,否则,返回一个新对象。
并将数组替换为原点。
let uniqueSkills = ['Using', 'Analyzing', 'Summarizing', 'Inferring', 'Predicting', 'Activating']
let data = {data0:[{count: 1, length: 1, skill: "Activating"},{count: 4, length: 1, skill: "Using"},{count: 2, length: 1, skill: "Analyzing"}],data1: [{count: 2, length: 1, skill: "Summarizing"}],data2: [{count: 1, length: 1, skill: "Predicting"},{count: 4, length: 1, skill: "Analyzing"}]};
Object.keys(data).forEach(key => {
data[key] =
uniqueSkills.map(skill => data[key].find(e => e.skill === skill) || { skill });
});
console.log(data);