从单个数组对象创建嵌套对象数组的通用函数
generic function to create an array of nested objects from a single object of arrays
这是一个非常具体的问题,但我有一个带有数组的对象:
let rawData = {
one: ["a", "a", "a", "b", "b", "b", "c", "c", "c"],
two: [1,2,3,1,2,3,1,2,3],
three: [1,4,9,3,9,7,6,5,5]
}
并且我想编写一个通用函数,它将根据第一个数组创建一组嵌套对象(这里是 a,但我想让这个函数不依赖于特定的键。
在我的第一次尝试中,我编写了一个将其解析为对象数组的函数:
dataframe_for_plot = (data) => {
var length
var names = []
for (var name in data) {
if (data.hasOwnProperty(name))
names.push(name);
length = rawData[name].length;
}
var results = [];
var item;
for (var row = 0; row < length; row++) {
item = {};
for (var col = 0; col < names.length; col++) {
item[names[col]] = data[names[col]][row];
}
results.push(item);
}
return results;
}
哪个产量
dataframe_for_plot(rawData)
[
{one: "a", two: 1, three: 1},
{one: "a", two: 2, three: 4},
{one: "a", two: 3, three: 9},
{one: "b", two: 1, three: 3},
{one: "b", two: 2, three: 9},
{one: "b", two: 3, three: 7},
{one: "c", two: 1, three: 6},
{one: "c", two: 2, three: 5},
{one: "c", two: 3, three: 5},
]
但我想在此函数的基础上构建以获得我想要的输出,其中第一个键用于根据该键的唯一编号(在本例中为 3)和新的 value
创建对象创建键以包含其他键的嵌套数组(在本例中为 two
和 three
,按 one
组合在一起)
let desired_output = [
{
one:"a",
values: [
{two:1, three:1},
{two:2, three:4},
{two:3, three:9}
],
},
{
one:"b",
values: [
{two:1, three:3},
{two:2, three:9},
{two:3, three:7}
],
},
{
one:"c",
values: [
{two:1, three:6},
{two:2, three:5},
{two:3, three:5}
],
}
]
我认为我的函数是一个好的开始,但我需要一些帮助来处理嵌套的第 2 部分!谢谢!
将对象转换为条目数组,并获得第一项的key
和vals
。将 vals
缩减为地图。对于第一个数组中的每个唯一值,如果值(在您的情况下为 one
),Map 将具有一个对象。然后迭代其他值的数组,从每个 [key, arr]
对中获取相应的值,并使用 Object.fromEntries()
.
将它们转换为对象
使用 Array.from()
.
将映射值迭代器转换回数组
const fn = obj => {
const [[key, vals], ...values] = Object.entries(obj)
return Array.from(vals.reduce((acc, v, i) => {
if(!acc.has(v)) acc.set(v, { [key]: v, values: [] })
acc.get(v).values.push(Object.fromEntries(
values.map(([k, arr]) => [k, arr[i]])
))
return acc
}, new Map()).values())
}
const rawData = {
one: ["a", "a", "a", "b", "b", "b", "c", "c", "c"],
two: [1,2,3,1,2,3,1,2,3],
three: [1,4,9,3,9,7,6,5,5]
}
const result = fn(rawData)
console.log(result)
如果您想控制属性的顺序,您可以传递一个 order
数组,然后按照您指定的顺序手动创建条目:
const fn = (order, obj) => {
const [[key, vals], ...values] = order.map(key => [key, obj[key]])
return Array.from(vals.reduce((acc, v, i) => {
if(!acc.has(v)) acc.set(v, { [key]: v, values: [] })
acc.get(v).values.push(Object.fromEntries(
values.map(([k, arr]) => [k, arr[i]])
))
return acc
}, new Map()).values())
}
const rawData = {
one: ["a", "a", "a", "b", "b", "b", "c", "c", "c"],
two: [1,2,3,1,2,3,1,2,3],
three: [1,4,9,3,9,7,6,5,5]
}
const result = fn(['one', 'three', 'two'], rawData)
console.log(result)
这是一个非常具体的问题,但我有一个带有数组的对象:
let rawData = {
one: ["a", "a", "a", "b", "b", "b", "c", "c", "c"],
two: [1,2,3,1,2,3,1,2,3],
three: [1,4,9,3,9,7,6,5,5]
}
并且我想编写一个通用函数,它将根据第一个数组创建一组嵌套对象(这里是 a,但我想让这个函数不依赖于特定的键。
在我的第一次尝试中,我编写了一个将其解析为对象数组的函数:
dataframe_for_plot = (data) => {
var length
var names = []
for (var name in data) {
if (data.hasOwnProperty(name))
names.push(name);
length = rawData[name].length;
}
var results = [];
var item;
for (var row = 0; row < length; row++) {
item = {};
for (var col = 0; col < names.length; col++) {
item[names[col]] = data[names[col]][row];
}
results.push(item);
}
return results;
}
哪个产量
dataframe_for_plot(rawData)
[
{one: "a", two: 1, three: 1},
{one: "a", two: 2, three: 4},
{one: "a", two: 3, three: 9},
{one: "b", two: 1, three: 3},
{one: "b", two: 2, three: 9},
{one: "b", two: 3, three: 7},
{one: "c", two: 1, three: 6},
{one: "c", two: 2, three: 5},
{one: "c", two: 3, three: 5},
]
但我想在此函数的基础上构建以获得我想要的输出,其中第一个键用于根据该键的唯一编号(在本例中为 3)和新的 value
创建对象创建键以包含其他键的嵌套数组(在本例中为 two
和 three
,按 one
组合在一起)
let desired_output = [
{
one:"a",
values: [
{two:1, three:1},
{two:2, three:4},
{two:3, three:9}
],
},
{
one:"b",
values: [
{two:1, three:3},
{two:2, three:9},
{two:3, three:7}
],
},
{
one:"c",
values: [
{two:1, three:6},
{two:2, three:5},
{two:3, three:5}
],
}
]
我认为我的函数是一个好的开始,但我需要一些帮助来处理嵌套的第 2 部分!谢谢!
将对象转换为条目数组,并获得第一项的key
和vals
。将 vals
缩减为地图。对于第一个数组中的每个唯一值,如果值(在您的情况下为 one
),Map 将具有一个对象。然后迭代其他值的数组,从每个 [key, arr]
对中获取相应的值,并使用 Object.fromEntries()
.
使用 Array.from()
.
const fn = obj => {
const [[key, vals], ...values] = Object.entries(obj)
return Array.from(vals.reduce((acc, v, i) => {
if(!acc.has(v)) acc.set(v, { [key]: v, values: [] })
acc.get(v).values.push(Object.fromEntries(
values.map(([k, arr]) => [k, arr[i]])
))
return acc
}, new Map()).values())
}
const rawData = {
one: ["a", "a", "a", "b", "b", "b", "c", "c", "c"],
two: [1,2,3,1,2,3,1,2,3],
three: [1,4,9,3,9,7,6,5,5]
}
const result = fn(rawData)
console.log(result)
如果您想控制属性的顺序,您可以传递一个 order
数组,然后按照您指定的顺序手动创建条目:
const fn = (order, obj) => {
const [[key, vals], ...values] = order.map(key => [key, obj[key]])
return Array.from(vals.reduce((acc, v, i) => {
if(!acc.has(v)) acc.set(v, { [key]: v, values: [] })
acc.get(v).values.push(Object.fromEntries(
values.map(([k, arr]) => [k, arr[i]])
))
return acc
}, new Map()).values())
}
const rawData = {
one: ["a", "a", "a", "b", "b", "b", "c", "c", "c"],
two: [1,2,3,1,2,3,1,2,3],
three: [1,4,9,3,9,7,6,5,5]
}
const result = fn(['one', 'three', 'two'], rawData)
console.log(result)