我有一个复杂的JSON对象。我正在尝试处理它以创建一个看起来像这样的数组:
[
[ "Name", "Spec", "Spec" ],
[ "Name", "Spec", "Spec" ]
]
这是我被困的地方:
let array = products.map((product) => {
return [
product.name,
product.attributes
.map((attribute) => (
attribute.spec
))
.reduce((accumulator, currentValue) => {
return accumulator.concat(currentValue);
}, [])
];
});
结果如下:
[
[ "Name", [ "Spec", "Spec" ] ],
[ "Name", [ "Spec", "Spec" ] ]
]
不可否认,我并不完全理解reduce
方法及其initialValue
参数。我知道使用该方法可以在map
的顶级使用中展平数组,但在更深层次上,似乎什么都不做。
我在线搜索但是只找到了涉及完全展平深度数组的答案。由于缺乏兼容性,flatten()
方法不是一种选择。
有人可以建议如何仅限二级吗?如果可能的话,我想通过改变数组来实现这一目标。
答案 0 :(得分:1)
你不需要那里的减速器 - 它只是让事情变得不必要地变得复杂。将attributes
映射到其spec
属性,然后使用spread:
const array = products.map(({ name, attributes }) => {
const specs = attributes.map(attribute => attribute.spec);
return [name, ...specs];
});
答案 1 :(得分:1)
您将reduce
放在错误的位置。你正在扁平化规格列表,这已经是一个扁平阵列。您想要展平具有名称和规范列表的列表。这是一种可能性:
const array = products.map(prod => [
prod.name,
prod.attributes.map(attr => attr.spec)
].reduce((acc, curr) => acc.concat(curr), []));
正如CertainPerformance指出的那样,有一个更简单的版本,我可能会稍微改写一下
const array = products.map(({name, attributes}) =>
[name, ...attributes.map(attr => attr.spec)]
);
flatten
该怎么办?从第一个解决方案中提取它作为可重用的函数。这不是新Array flatten
方法的完全替代品,但它可能就是您所需要的:
const flatten = arr => arr.reduce((acc, curr) => acc.concat(curr), [])
const array = products.map(prod => flatten([
prod.name,
prod.attributes.map(attr => attr.spec)
])
)
reduce
调用如何平整一个级别?我们可以将[x, y, z].reduce(fn, initial)
视为执行这些步骤
fn(initial, x)
,产生价值a
fn(a, y)
,产生价值b
fn(b, z)
,产生价值c
c
换句话说,[x, y, z].reduce(fn, initial)
会返回fn(fn(fn(initial, x), y), z)
。
当fn
为(acc, val) => acc.concat(val)
时,我们可以将['name', ['spec1', 'spec2']].reduce(fn, [])
视为fn(fn([], 'name'), ['spec1', 'spec2'])
,这与([].concat('name')).concat(['spec1', 'spec2'])
相同,当然是['name', 'spec1', 'spec2']
{1}}。
我很高兴你问。 : - )
有一次重大失败。您没有包含任何样本数据。要解决此问题,需要尝试从代码中重建数据格式。给出一个最小的例子很简单,例如:
const products = [
{name: 'foo', attributes: [{spec: 'bar'}, {spec: 'baz'}]},
{name: 'oof', attributes: [{spec: 'rab'}, {spec: 'zab'}]}
]
具有匹配的预期输出:
[
["foo", "bar", "baz"],
["oof", "rab", "zab"]
]
现在你提到它,这似乎是一个奇怪的结构。你可能有充分的理由,但这很奇怪。
数组通常在Javascript中有两个用途。它们是相同类型的元素的任意长度列表,或者它们是固定长度列表,每个索引都有特定类型(又名元组。)
但是你的结构结合了这两者。它们是任意的 - (至少看起来如此)长度列表,其中第一个条目是名称,后续条目是规格。虽然可能有理由这样做,但您可能需要考虑这种结构是否特别有用。
如果可能的话,我想通过改变数组来实现这一目标。
我拒绝参加这样的恐怖事件。
但是,严肃地说,不可变数据使得编码更容易。您是否有任何真正的理由将其列为要求?