如何将具有动态键名和嵌套数组的对象数组简化为更简单的格式?
How to simplify an array of objects with dynamic key names and a nested array into a simpler format?
我正在尝试将具有键的对象数组转换为:name
和 winRatio
到另一个对象数组,其键是 winRatio 数组中项目的每个唯一名称和值。
这个问题的目的是将输入的数据转换并重新格式化为图表实现解决方案(Recharts,如果您有兴趣)
输入
const data = [
{
name: 'Tyler',
winRatio: [1, 0.5, 0.6666666666666666],
},
{
name: 'Lizzie',
winRatio: [0, 0.5, 0.3333333333333333],
},
];
输出
const formatted = [
{
index: 0,
Tyler: 1,
Lizzie: 0,
},
{
index: 1,
Tyler: 0.5,
Lizzie: 0.5,
},
{
index: 2,
Tyler: 0.6666,
Lizzie: .333,
},
];
我考虑过使用 map 和 reduce 数组函数,但我似乎无法完全理解它。
备注
此外,输出中的每个对象都应该有一个与该对象关联的索引值,该索引值递增 1。
备注
输出数组的长度应等于任何 winRatio 数组的最长长度。例如,如果 'Tyler' 的 winRatio 有 20 个项目,则输出数组应该有 20 个对象。
这是您可以使用减速器执行此操作的一种方法。它循环遍历数据数组,获取每个玩家对象并以您请求的格式将其组合到最终数组中。
const reducer = (previousValue, currentValue,index) => {
let current = {}
currentValue.winRatio.forEach( (x, index) => {
current = previousValue[index] ?? { index };
current[currentValue.name] = x
previousValue[index] = current
})
return previousValue
}
data.reduce(reducer, [])
至于你的两个笔记,输出是一个数组,所以它应该知道它的索引,但你可以在这个例子中的 forEach 块中添加一行,如果没有,则添加一个索引 key/value 对当你循环通过时还存在。对于你的第二个注意事项,我不确定如何在不首先对数组进行排序(或遍历它并注意最长的 winRatio 长度)的情况下解决这个问题,所以我想你可以这样做。
相当直接地使用 Object .fromEntries
可能会有所帮助:
const format = (xs) =>
Array .from ({length: Math .max (...xs .map ((x) => x .winRatio .length))},
(_, i) => Object .fromEntries ([
['index', i],
... data .filter (({winRatio}) => winRatio .length > i)
.map (({name, winRatio}) => [name, winRatio [i]])
])
)
const data = [{name: 'Tyler', winRatio: [1, 0.5, 0.6666666666666666]}, {name: 'Lizzie', winRatio: [0, 0.5, 0.3333333333333333]}];
console .log (format (data))
.as-console-wrapper {max-height: 100% !important; top: 0}
我们计算最长的 winRatio
数组的长度,创建一个该长度的新数组,然后为新数组中的每个索引,在数组上使用 Object .fromEntries
创建一个对象包括对该索引的引用以及每个在该索引处有一个条目的 name
和第 n 个 winRatio
。
我正在尝试将具有键的对象数组转换为:name
和 winRatio
到另一个对象数组,其键是 winRatio 数组中项目的每个唯一名称和值。
这个问题的目的是将输入的数据转换并重新格式化为图表实现解决方案(Recharts,如果您有兴趣)
输入
const data = [
{
name: 'Tyler',
winRatio: [1, 0.5, 0.6666666666666666],
},
{
name: 'Lizzie',
winRatio: [0, 0.5, 0.3333333333333333],
},
];
输出
const formatted = [
{
index: 0,
Tyler: 1,
Lizzie: 0,
},
{
index: 1,
Tyler: 0.5,
Lizzie: 0.5,
},
{
index: 2,
Tyler: 0.6666,
Lizzie: .333,
},
];
我考虑过使用 map 和 reduce 数组函数,但我似乎无法完全理解它。
备注 此外,输出中的每个对象都应该有一个与该对象关联的索引值,该索引值递增 1。
备注 输出数组的长度应等于任何 winRatio 数组的最长长度。例如,如果 'Tyler' 的 winRatio 有 20 个项目,则输出数组应该有 20 个对象。
这是您可以使用减速器执行此操作的一种方法。它循环遍历数据数组,获取每个玩家对象并以您请求的格式将其组合到最终数组中。
const reducer = (previousValue, currentValue,index) => {
let current = {}
currentValue.winRatio.forEach( (x, index) => {
current = previousValue[index] ?? { index };
current[currentValue.name] = x
previousValue[index] = current
})
return previousValue
}
data.reduce(reducer, [])
至于你的两个笔记,输出是一个数组,所以它应该知道它的索引,但你可以在这个例子中的 forEach 块中添加一行,如果没有,则添加一个索引 key/value 对当你循环通过时还存在。对于你的第二个注意事项,我不确定如何在不首先对数组进行排序(或遍历它并注意最长的 winRatio 长度)的情况下解决这个问题,所以我想你可以这样做。
相当直接地使用 Object .fromEntries
可能会有所帮助:
const format = (xs) =>
Array .from ({length: Math .max (...xs .map ((x) => x .winRatio .length))},
(_, i) => Object .fromEntries ([
['index', i],
... data .filter (({winRatio}) => winRatio .length > i)
.map (({name, winRatio}) => [name, winRatio [i]])
])
)
const data = [{name: 'Tyler', winRatio: [1, 0.5, 0.6666666666666666]}, {name: 'Lizzie', winRatio: [0, 0.5, 0.3333333333333333]}];
console .log (format (data))
.as-console-wrapper {max-height: 100% !important; top: 0}
我们计算最长的 winRatio
数组的长度,创建一个该长度的新数组,然后为新数组中的每个索引,在数组上使用 Object .fromEntries
创建一个对象包括对该索引的引用以及每个在该索引处有一个条目的 name
和第 n 个 winRatio
。