javascript - 如何仅将多维数组的一部分展平一层?
问题描述
我有一个复杂的 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()
方法不是一种选择。
有人可以建议如何仅展平第二层吗?如果可能的话,我想通过改变数组来实现这一点。
解决方案
1. 为什么会失败?
你把你reduce
的放在错误的地方。您正在展平规格列表,这已经是一个平面阵列。您想要展平具有名称和规格列表的列表。这是一种可能性:
const array = products.map(prod => [
prod.name,
prod.attributes.map(attr => attr.spec)
].reduce((acc, curr) => acc.concat(curr), []));
2. 什么是更好的解决方案?
正如CertainPerformance 指出的那样,有一个更简单的版本,我可能会稍微不同地写成
const array = products.map(({name, attributes}) =>
[name, ...attributes.map(attr => attr.spec)]
);
3. 如果需要flatten
在其他地方重复使用怎么办?
从第一个解决方案中提取它作为可重用函数。这不是新 Arrayflatten
方法的完全替代品,但它可能就是您所需要的:
const flatten = arr => arr.reduce((acc, curr) => acc.concat(curr), [])
const array = products.map(prod => flatten([
prod.name,
prod.attributes.map(attr => attr.spec)
])
)
4. 那调用如何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']
。
5. 我的问题有什么问题吗?
我很高兴你问。:-)
有一个重大失败。您没有包含任何示例数据。为了帮助解决这个问题,需要尝试从代码中重建数据格式。举一个最小的例子就很容易了,例如:
const products = [
{name: 'foo', attributes: [{spec: 'bar'}, {spec: 'baz'}]},
{name: 'oof', attributes: [{spec: 'rab'}, {spec: 'zab'}]}
]
具有匹配的预期输出:
[
["foo", "bar", "baz"],
["oof", "rab", "zab"]
]
6. 我的输出结构怎么样?
既然你提到它,这似乎是一个奇怪的结构。你可能有充分的理由,但这很奇怪。
数组在 Javascript 中通常有两个用途。它们要么是相同类型的任意长度的元素列表,要么是固定长度的列表,每个索引都有特定的类型(又名tuples。)
但是你的结构结合了这两者。它们是任意的(至少看起来如此)长度列表,其中第一个条目是名称,后续条目是规范。虽然这可能是有道理的,但您可能需要考虑这种结构是否特别有用。
7. 我怎样才能做到这一点而不发生变异?
如果可能的话,我想通过改变数组来实现这一点。
我拒绝参与这样的恐怖活动。
不过,说真的,不可变数据使编码变得更加容易。您将其列为要求是否有任何真正的原因?
推荐阅读
- php - Laravel 语言环境不采用其他日期格式
- python - 如何回复我输入的频道之外的消息?
- javascript - Vuejs - 通过 lodash 去抖动,传递“等待”参数
- oracle - 如何在目标中识别附加到目标 Oracle 表且随后从其数据源中删除的数据记录?
- r - 如何根据从外部数据框中检索数据的公式添加列?
- java - JNI MattoBitmap 异常
- reactjs - 功能组件定义范围导致应用程序无法正常工作,但我不明白为什么
- javascript - 天数停止在零
- python - Exclude zero from np.linspace in one line
- go - 由于间接导入相同的依赖项,防止 Go 模块覆盖直接依赖项版本