将 excel 二维数组转换为包含列名的嵌套属性对象
Posted
技术标签:
【中文标题】将 excel 二维数组转换为包含列名的嵌套属性对象【英文标题】:Transform excel 2D array into nested properties object with column names included 【发布时间】:2020-03-27 07:49:05 【问题描述】:我有一个 Excel 文件如下:
[["Country", "City", "Zip"], ["CNTR1", "CT1", 101], ["CNTR1", "CT2", 102], ["CNTR2", "CT3", 103]]
以上是Excel 4行的二维数组解释。我想从上面得到以下对象:
level1: "Country",
items: [
"CNTR1":
level2: "City",
items: [
"CT1":
level3: "Zip",
items: [
"101"
]
,
"CT2":
level3: "Zip",
items: [
"102"
]
]
,
"CNTR2":
level2: "City",
items: [
"CT3":
level3: "Zip",
items: [
"103"
]
]
]
主要目的是有一个层次结构,因为上面的 Excel 应该有一个从左到右的依赖关系,因为这些值将在依赖下拉列表中使用(所以如果我们有国家“CNTR1”,所有城市和邮政编码应该是其对象的一部分,因为在国家下拉列表中选择“CNTR1”后,只有 CT1 和 CT2 应该显示在城市下拉列表中,以此类推邮政编码),并且基于这种依赖关系,我们应该有每个的子值嵌套级别。此外,上述内容不应仅限于三层深度,因此应该使用 reducers/recursive 解决方案。
如果有人有更好的对象模式解决方案,因为我认为以上内容既符合依赖下拉列表的目的,同时也检索列名,请随时分享。下拉列表将是动态的,依赖于从左到右的列,并且值基于相同的“更高”层次结构值。
希望它足够清楚。
到目前为止,我有:
items.map(row => row.reduceRight((value, key) => ([key]: value))).reduce((acc, value) => (Object.assign(acc, value)))
但是这个只是给出类型的结果:
"CNTR1":
"CT2": 102
,
"CNTR2":
"CT3": 103
(忽略嵌套属性数据的丢失,因为合并不深)列的名称不包括在内,对于指定的目的,数据结构似乎有点差。
谢谢
【问题讨论】:
【参考方案1】:您可以通过减少嵌套数组来减少数组并构建所需的结构。并重新调整内部 items
数组。
var data = [["Country", "City", "Zip"], ["CNTR1", "CT1", 101], ["CNTR1", "CT2", 102], ["CNTR2", "CT3", 103]],
result = data.reduce((r, [...a], i, [0]: header ) =>
var last = a.pop();
if (i === 1) r = level1: header[0], items: [] ;
a.reduce((items, k, i) =>
var temp = items.find(q => k in q);
if (!temp) items.push(temp = [k]: ['level' + (i + 2)]: header[i + 1], items: [] );
return temp[k].items;
, r.items).push(last);
return r;
);
console.log(result);
.as-console-wrapper max-height: 100% !important; top: 0;
【讨论】:
是的,谢谢,就是这样。您认为这种结构是否适合指定的目的?我在想level
键中的索引可能是多余的,因为它可以在迭代期间轻松检索,但除此之外,我认为它有助于深入遍历不需要任何查询的依赖元素在同一级别。
我不知道 excel 如何为此目的工作。但如果这是你需要的结构,那就去吧。 (我个人会选择一些不改变属性的东西,比如level
,并使用一种无需检索具有更扁平数据结构的密钥的格式。)
嗯,Excel 更像是一个数据提供者,但归根结底,问题开头提供的数组是检索到的数据。目的是派生从左到右的父子关系,并创建一种树,同时还保持关卡的名称。你能提供一个你提到的平面结构的简单对象吗?谢谢
可能是这样的: level: 1, value: "Country", items: [ level: 2, value: "City", key: "CNTR1", items: [ level: 3, key: "CT1", value: "Zip", items: [101] , level: 3, key: "CT2", value: "Zip", items: [102] ] , level: 2, key: "CNTR2", value: "City", items: [ level: 3, key: "CT3", value: "Zip", items: [103] ] ]
我明白了,所以与其将键作为属性,不如将它放在对象内部,并且它更有条理。谢谢。【参考方案2】:
您可以使用reduce
方法创建类似的结构,方法是从数组中的第一个元素切片,然后从数组中的第一个元素获取当前级别。
const data = [["Country", "City", "Zip"], ["CNTR1", "CT1", 101], ["CNTR1", "CT2", 102], ["CNTR2", "CT3", 103]]
function build(data, level)
return data.slice(1).reduce((r, a) =>
a.reduce((ac, e, i, arr) =>
ac.level = data[0][i]
if (arr[i + 1]) ac[e] = (ac[e] || )
else ac.value = e;
return ac[e];
, r)
return r
, )
const result = build(data);
console.log(result)
【讨论】:
以上将覆盖最后一级键。用这个数组检查它:const data = [["Country", "City", "Zip"], ["CNTR1", "CT1", 101], ["CNTR1", "CT1", 102], ["CNTR2", "CT3", 103]]
结果将是: "level": "Country", "CNTR1": "level": "City", "CT1": "level": "Zip", "value": 102 , "CNTR2": "level": "City", "CT3": "level": "Zip", "value": 103
101 邮政编码将丢失。以上是关于将 excel 二维数组转换为包含列名的嵌套属性对象的主要内容,如果未能解决你的问题,请参考以下文章