【问题标题】:Transform excel 2D array into nested properties object with column names included将 excel 二维数组转换为包含列名的嵌套属性对象
【发布时间】: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
  }
}

(忽略嵌套属性数据的丢失,因为合并不深)列的名称不包括在内,对于指定的目的,数据结构似乎有点差。

谢谢

【问题讨论】:

    标签: javascript arrays json reactjs javascript-objects


    【解决方案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 邮政编码将丢失。
    猜你喜欢
    • 2016-10-01
    • 2014-12-30
    • 2020-01-08
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 2015-12-22
    相关资源
    最近更新 更多