对于我当前的项目,我正在使用返回格式如下的数据的API:
{
groups: [
{
items: [
{
points: [
{ name: "name1", ... },
{ name: "name2", ... },
{ name: "name3", ... },
...
],
...
},
...
]
},
...
],
...
};
我想创建一个纯函数,mapValues
,它接受上述格式的对象,以及映射每个name
的对象到value
,并返回相同的结构,但每个point
包含与其value
对应的name
。
例如,调用mapValues(data, { name1: "value1", name2: "value2", name3: "value3" })
应该返回:
{
groups: [
{
items: [
{
points: [
{ name: "name1", value: "value1", ... },
{ name: "name2", value: "value2", ... },
{ name: "name3", value: "value3", ... },
...
],
...
},
...
]
},
...
],
...
};
这是我的第一遍:
function mapValues(data, values) {
return _.extend({}, data, {
groups: _.map(ui.groups, (group) => {
return _.extend({}, group, {
items: _.map(group.items, (item) => {
return _.extend({}, item, {
points: _.map(item.points, (point) => {
return _.extend({ value: values[point.name] }, point);
})
});
})
});
})
});
}
这样可行,但有很多嵌套重复的代码。对于我的第二次尝试,我到达了递归。
function mapValues(data, values) {
return (function recursiveMap(object, attributes) {
if (attributes.length === 0) { return _.extend({ value: values[object.name] }, object); }
let key = attributes[0];
return _.extend({}, object, {
[key]: _.map(object[key], child => recursiveMap(child, attributes.slice(1)))
});
})(ui, ["groups", "items", "points"]);
}
这也有效,但它难以阅读而且不够简洁。
是否有更简洁的方法使用Lodash递归地映射对象?理想情况下,我正在寻找一种功能性方法。
答案 0 :(得分:1)
这是一种使用Object.assign
而不是花哨功能
var data = <your data here>;
var values = <your mapped values>;
data.groups.items.points.map(p=>
Object.assign(p, {value: values[p.name]})
);
这是有效的,因为数组和对象是pass by reference。因此,对值的任何修改都将导致原始文件被更改。
如果您不想改变原始数据集,则需要使用{}
作为第一个参数(分配给新的空对象)并为每个对象显示清晰的读/写路径。
var newData = Object.assign({}, data,
{groups:
{items:
{points: data.groups.items.points.map(p=>
Object.assign({}, p, {value: values[p.name]})
)}
}
}
);
答案 1 :(得分:0)
我知道你想要Lodash,但我前段时间遇到了同样的问题而且我已经想出了JSFiddle我正在使用由nervgh创建的强大工具。它非常简单但有用。您可以使用Object.assign
将此函数调整为纯函数,接受关键参数并根据需要进行调整。你明白了。
function mapValues(data, values) {
var iterator = new RecursiveIterator(data);
for(let {node} of iterator) {
if(node.hasOwnProperty('name')) {
node.value = values[node.name];
}
}
return data;
}