将对象中的键值提取到具有特定字段的对象数组中
Extracting key value from object into array of objects with specific fields
所以我有这个数据:
fields = ['a', 'b', 'c']
data = [{r: 1, a: 2, b: 3, c: 4, h: 5}, {r: 4, a: 9, b: 1, c: 4, h: 5} ... ]
并且我希望能够(首选 lodash)能够做到这一点:
newData = [{r:1, h:5, values: [{name: 'a', value: 2},{name: 'b', value: 3}, {name: 'c', value: 4}], .....]
意味着只从数组中的每个对象中取出 'fields' 对象的字段(它们始终存在)并放入 'values' 属性 中此处显示的格式。
很想听听实现这一目标的最简洁方法的建议!
我这样做了:
function something(data, fields) {
const formattedData = _.map(data, (currData) => {
const otherFields = _.omit(currData, fields)
return {
...otherFields,
values: _.flow(
currData => _.pick(currData, fields),
pickedFields => _.toPairs(pickedFields),
pairs => _.map(pairs, pair => {
return { name: pair[0], value: pair[1] }
})
)(currData)
}
})
return formattedData
}
哪个可行,但我想知道它是否有点复杂。
您可以map
遍历数据中的对象,然后检查键是否在字段数组中:
fields = ["a", "b", "c"];
data = [
{ r: 1, a: 2, b: 3, c: 4, h: 5 },
{ r: 4, a: 9, b: 1, c: 4, h: 5 },
];
let newData = data.map((o) => {
let newObject = {};
newObject.values = [];
for (let k in o) {
if (fields.includes(k)) {
newObject.values.push({
name: k,
value: o[k]
});
} else {
newObject[k] = o[k];
}
}
return newObject;
});
console.log(newData);
您可以解构对象,选择所需的属性,然后 return 对象的其余部分具有所需的值。
const
fields = ['a', 'b', 'c'],
data = [{ r: 1, a: 2, b: 3, c: 4, h: 5 }, { r: 4, a: 9, b: 1, c: 4, h: 5 }],
result = data.map(o => {
const values = fields.map(name => {
let value;
({ [name]: value, ...o } = o);
return { name, value };
});
return { ...o, values };
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
_.flow()
方法创建一个函数,您可以提取和命名该函数。此外,流程中的第一个函数接受超过 1 个参数,因此您无需显式传递它。由于 _.toPairs()
是一元的,因此您不需要将其包装在箭头函数中。
对象创建有点烦人。我用过_.zipObject()
,但还是很麻烦。
现在您可以在主函数中使用 _.flow()
创建的函数,它的可读性很好:
const { flow, pick, toPairs, map, partial, zipObject, omit } = _
const propsToObjs = flow(
pick,
toPairs,
pairs => map(pairs, partial(zipObject, ['name', 'value'])),
)
const fn = (data, fields) =>
map(data, currData => ({
...omit(currData, fields),
values: propsToObjs(currData, fields)
}))
const fields = ['a', 'b', 'c']
const data = [{r: 1, a: 2, b: 3, c: 4, h: 5}, {r: 4, a: 9, b: 1, c: 4, h: 5}]
const result = fn(data, fields)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
使用 lodash/fp,我们可以使流函数更好,因为 lodash/fp 函数是自动柯里化和迭代优先数据最后(不是参数的相反顺序):
const { flow, pick, toPairs, map, partial, zipObject, omit } = _
const propsToObjs = flow(
pick,
toPairs,
map(zipObject(['name', 'value']))
)
const fn = fields => map(currData => ({
...omit(fields, currData),
values: propsToObjs(fields, currData)
}))
const fields = ['a', 'b', 'c']
const data = [{r: 1, a: 2, b: 3, c: 4, h: 5}, {r: 4, a: 9, b: 1, c: 4, h: 5}]
const result = fn(fields)(data)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
所以我有这个数据:
fields = ['a', 'b', 'c']
data = [{r: 1, a: 2, b: 3, c: 4, h: 5}, {r: 4, a: 9, b: 1, c: 4, h: 5} ... ]
并且我希望能够(首选 lodash)能够做到这一点:
newData = [{r:1, h:5, values: [{name: 'a', value: 2},{name: 'b', value: 3}, {name: 'c', value: 4}], .....]
意味着只从数组中的每个对象中取出 'fields' 对象的字段(它们始终存在)并放入 'values' 属性 中此处显示的格式。
很想听听实现这一目标的最简洁方法的建议!
我这样做了:
function something(data, fields) {
const formattedData = _.map(data, (currData) => {
const otherFields = _.omit(currData, fields)
return {
...otherFields,
values: _.flow(
currData => _.pick(currData, fields),
pickedFields => _.toPairs(pickedFields),
pairs => _.map(pairs, pair => {
return { name: pair[0], value: pair[1] }
})
)(currData)
}
})
return formattedData
}
哪个可行,但我想知道它是否有点复杂。
您可以map
遍历数据中的对象,然后检查键是否在字段数组中:
fields = ["a", "b", "c"];
data = [
{ r: 1, a: 2, b: 3, c: 4, h: 5 },
{ r: 4, a: 9, b: 1, c: 4, h: 5 },
];
let newData = data.map((o) => {
let newObject = {};
newObject.values = [];
for (let k in o) {
if (fields.includes(k)) {
newObject.values.push({
name: k,
value: o[k]
});
} else {
newObject[k] = o[k];
}
}
return newObject;
});
console.log(newData);
您可以解构对象,选择所需的属性,然后 return 对象的其余部分具有所需的值。
const
fields = ['a', 'b', 'c'],
data = [{ r: 1, a: 2, b: 3, c: 4, h: 5 }, { r: 4, a: 9, b: 1, c: 4, h: 5 }],
result = data.map(o => {
const values = fields.map(name => {
let value;
({ [name]: value, ...o } = o);
return { name, value };
});
return { ...o, values };
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
_.flow()
方法创建一个函数,您可以提取和命名该函数。此外,流程中的第一个函数接受超过 1 个参数,因此您无需显式传递它。由于 _.toPairs()
是一元的,因此您不需要将其包装在箭头函数中。
对象创建有点烦人。我用过_.zipObject()
,但还是很麻烦。
现在您可以在主函数中使用 _.flow()
创建的函数,它的可读性很好:
const { flow, pick, toPairs, map, partial, zipObject, omit } = _
const propsToObjs = flow(
pick,
toPairs,
pairs => map(pairs, partial(zipObject, ['name', 'value'])),
)
const fn = (data, fields) =>
map(data, currData => ({
...omit(currData, fields),
values: propsToObjs(currData, fields)
}))
const fields = ['a', 'b', 'c']
const data = [{r: 1, a: 2, b: 3, c: 4, h: 5}, {r: 4, a: 9, b: 1, c: 4, h: 5}]
const result = fn(data, fields)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
使用 lodash/fp,我们可以使流函数更好,因为 lodash/fp 函数是自动柯里化和迭代优先数据最后(不是参数的相反顺序):
const { flow, pick, toPairs, map, partial, zipObject, omit } = _
const propsToObjs = flow(
pick,
toPairs,
map(zipObject(['name', 'value']))
)
const fn = fields => map(currData => ({
...omit(fields, currData),
values: propsToObjs(fields, currData)
}))
const fields = ['a', 'b', 'c']
const data = [{r: 1, a: 2, b: 3, c: 4, h: 5}, {r: 4, a: 9, b: 1, c: 4, h: 5}]
const result = fn(fields)(data)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>