使用路径从对象中提取数据 - 包括数组中的所有数据
Extract data from object using a path - include all data in arrays
我正在尝试用 LoDash 解决以下问题。我知道如何使用 for 循环解决问题,但我正在寻找解决问题的现代函数方法。
我有以下数据:
const data = {
people: [
{
name: "Bob",
vehicles: [
{
model: "Mazda"
tires: [
{ pressure: 20 },
{ pressure: 22 },
{ pressure: 23 },
{ pressure: 21 },
]
},
{
model: "Harley Davidson"
tires: [
{ pressure: 20 }
{ pressure: 25 }
]
}
]
},
{...},
{...},
{...},
]
}
我想从中提取属于每个人的每个轮胎压力的列表。所以像这样:
[20, 22, 23, 21, 20, 25, ... ]
我正在寻找的是一种可以像这样调用的方法:
const path = 'people.vehicles[*].tires[*].pressure';
const tirePressure = _.methodName(data, path);
我知道 lodash 支持一些类似的功能——比如 _.at(object, ['a[0].b.c', 'a[1]']);
(link),但据我所知,它不支持折叠整个数组。
您可以采用经典的迭代和递归方法,return 仅找到 pressure
的值。
function getPressures(o) {
return [].concat(...Object.entries(o).map(([key, value]) =>
key === 'pressure'
? value
: value && typeof value === 'object'
? getPressures(value)
: []
));
}
var data = { people: [{ name: "Bob", vehicles: [{ model: "Mazda", tires: [{ pressure: 20 }, { pressure: 22 }, { pressure: 23 }, { pressure: 21 }] }, { model: "Harley Davidson", tires: [{ pressure: 20 }, { pressure: 25 }] }] }] };
console.log(getPressures(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
另一种方法是为使用通配符的路径实现 get 方法,结果是一个以路径作为键和所需值的对象。
function get(object, path) {
function iter(o, p, i) {
if (i === parts.length) {
result[p.join('.')] = o;
return;
}
if (!o || typeof o !== 'object') {
return;
}
if (parts[i] === '*') {
Object
.entries(o)
.forEach(([k, v]) => iter(v, p.concat(k), i + 1));
return;
}
if (parts[i] in o) {
iter(o[parts[i]], p.concat(parts[i]), i + 1);
}
}
var result = {},
parts = path.split('.');
iter(object, [], 0);
return result;
}
var data = { people: [{ name: "Bob", vehicles: [{ model: "Mazda", tires: [{ pressure: 20 }, { pressure: 22 }, { pressure: 23 }, { pressure: 21 }] }, { model: "Harley Davidson", tires: [{ pressure: 20 }, { pressure: 25 }] }] }] },
result = get(data, 'people.*.vehicles.*.tires.*.pressure'),
values = Object.values(result);
console.log(result);
console.log(values);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我会用简单的 JS
喜欢
使用.map
获取轮胎值,然后展平这个数组
const data = {
people: [
{
name: "Bob",
vehicles: [
{
model: "Mazda",
tires: [
{ pressure: 20 },
{ pressure: 22 },
{ pressure: 23 },
{ pressure: 21 },
]
},
{
model: "Harley Davidson",
tires: [
{ pressure: 20 },
{ pressure: 25 }
]
}
]
}
]
}
var x= data.people[0].vehicles.map(o=> o.tires.map(i=> i.pressure))
console.log(x.join(",").split(","))
为了提取属于每个人的每个轮胎压力的列表,您可以使用 reduce
并将所有轮胎压力值分组到各自的名称,并使用对象数据结构来存储输出:
const data={people:[{name:"Bob",vehicles:[{model:"Mazda",tires:[{pressure:20},{pressure:22},{pressure:23},{pressure:21}]},{model:"Harley Davidson",tires:[{pressure:20},{pressure:25}]}]}]};
const result = data.people.reduce((all, {name, vehicles}) => {
const pressures = vehicles.reduce((total, {tires}) => {
tires.forEach(({pressure}) => total.push(pressure));
return total;
}, []);
all[name] = pressures;
return all;
}, {});
console.log(result);
您可以使用 Lodash's flatMap
. This could probably get shorter using flatMapDeep
实现,但恕我直言,这样会更清晰。
const data = {
people: [
{
name: "Bob",
vehicles: [
{
model: "Mazda",
tires: [
{ pressure: 20 },
{ pressure: 22 },
{ pressure: 23 },
{ pressure: 21 },
]
},
{
model: "Harley Davidson",
tires: [
{ pressure: 20 },
{ pressure: 25 }
]
}
]
}
]
};
const pressures = _(data.people)
.flatMap(_.property('vehicles'))
.flatMap(_.property('tires'))
.map(_.property('pressure'))
.value();
console.log(pressures);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
我正在尝试用 LoDash 解决以下问题。我知道如何使用 for 循环解决问题,但我正在寻找解决问题的现代函数方法。
我有以下数据:
const data = {
people: [
{
name: "Bob",
vehicles: [
{
model: "Mazda"
tires: [
{ pressure: 20 },
{ pressure: 22 },
{ pressure: 23 },
{ pressure: 21 },
]
},
{
model: "Harley Davidson"
tires: [
{ pressure: 20 }
{ pressure: 25 }
]
}
]
},
{...},
{...},
{...},
]
}
我想从中提取属于每个人的每个轮胎压力的列表。所以像这样:
[20, 22, 23, 21, 20, 25, ... ]
我正在寻找的是一种可以像这样调用的方法:
const path = 'people.vehicles[*].tires[*].pressure';
const tirePressure = _.methodName(data, path);
我知道 lodash 支持一些类似的功能——比如 _.at(object, ['a[0].b.c', 'a[1]']);
(link),但据我所知,它不支持折叠整个数组。
您可以采用经典的迭代和递归方法,return 仅找到 pressure
的值。
function getPressures(o) {
return [].concat(...Object.entries(o).map(([key, value]) =>
key === 'pressure'
? value
: value && typeof value === 'object'
? getPressures(value)
: []
));
}
var data = { people: [{ name: "Bob", vehicles: [{ model: "Mazda", tires: [{ pressure: 20 }, { pressure: 22 }, { pressure: 23 }, { pressure: 21 }] }, { model: "Harley Davidson", tires: [{ pressure: 20 }, { pressure: 25 }] }] }] };
console.log(getPressures(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
另一种方法是为使用通配符的路径实现 get 方法,结果是一个以路径作为键和所需值的对象。
function get(object, path) {
function iter(o, p, i) {
if (i === parts.length) {
result[p.join('.')] = o;
return;
}
if (!o || typeof o !== 'object') {
return;
}
if (parts[i] === '*') {
Object
.entries(o)
.forEach(([k, v]) => iter(v, p.concat(k), i + 1));
return;
}
if (parts[i] in o) {
iter(o[parts[i]], p.concat(parts[i]), i + 1);
}
}
var result = {},
parts = path.split('.');
iter(object, [], 0);
return result;
}
var data = { people: [{ name: "Bob", vehicles: [{ model: "Mazda", tires: [{ pressure: 20 }, { pressure: 22 }, { pressure: 23 }, { pressure: 21 }] }, { model: "Harley Davidson", tires: [{ pressure: 20 }, { pressure: 25 }] }] }] },
result = get(data, 'people.*.vehicles.*.tires.*.pressure'),
values = Object.values(result);
console.log(result);
console.log(values);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我会用简单的 JS
喜欢
使用.map
获取轮胎值,然后展平这个数组
const data = {
people: [
{
name: "Bob",
vehicles: [
{
model: "Mazda",
tires: [
{ pressure: 20 },
{ pressure: 22 },
{ pressure: 23 },
{ pressure: 21 },
]
},
{
model: "Harley Davidson",
tires: [
{ pressure: 20 },
{ pressure: 25 }
]
}
]
}
]
}
var x= data.people[0].vehicles.map(o=> o.tires.map(i=> i.pressure))
console.log(x.join(",").split(","))
为了提取属于每个人的每个轮胎压力的列表,您可以使用 reduce
并将所有轮胎压力值分组到各自的名称,并使用对象数据结构来存储输出:
const data={people:[{name:"Bob",vehicles:[{model:"Mazda",tires:[{pressure:20},{pressure:22},{pressure:23},{pressure:21}]},{model:"Harley Davidson",tires:[{pressure:20},{pressure:25}]}]}]};
const result = data.people.reduce((all, {name, vehicles}) => {
const pressures = vehicles.reduce((total, {tires}) => {
tires.forEach(({pressure}) => total.push(pressure));
return total;
}, []);
all[name] = pressures;
return all;
}, {});
console.log(result);
您可以使用 Lodash's flatMap
. This could probably get shorter using flatMapDeep
实现,但恕我直言,这样会更清晰。
const data = {
people: [
{
name: "Bob",
vehicles: [
{
model: "Mazda",
tires: [
{ pressure: 20 },
{ pressure: 22 },
{ pressure: 23 },
{ pressure: 21 },
]
},
{
model: "Harley Davidson",
tires: [
{ pressure: 20 },
{ pressure: 25 }
]
}
]
}
]
};
const pressures = _(data.people)
.flatMap(_.property('vehicles'))
.flatMap(_.property('tires'))
.map(_.property('pressure'))
.value();
console.log(pressures);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>