【问题标题】:transform an array from a flat 1 dimensional to a tree like in javascript/lodash将数组从平面一维转换为树,如 javascript/lodash
【发布时间】:2020-08-19 00:04:36
【问题描述】:

我无法将以下数组 data1 转换为看起来像 data2:我尝试使用 lodash 但它有点奇怪 _gropuby 给了我一个对象数组。我应该在数组内部循环...为此创建一个自定义函数。或者 lodash 中是否有一个技巧来简化这一点。谢谢 /************************************************* *************************************************

let data1 = [{
    KlasCode: "AA",
    LESDatum: "06/02/2017",
    LESID: "1",
    ModuleID: "1061",
    ParticipationLetterCode: "Y"
  }, {
    KlasCode: "AA",
    LESDatum: "07/02/2017",
    LESID: "2",
    ModuleID: "1061",
    ParticipationLetterCode: "X",
  },
  {
    KlasCode: "AA",
    LESDatum: "13/02/2017",
    LESID: "3",
    ModuleID: "1062",
    ParticipationLetterCode: "Z"
  },
  {
    KlasCode: "BB",
    LESDatum: "16/02/2017",
    LESID: "4",
    ModuleID: "1063",
    ParticipationLetterCode: "X"
  }
]

//The output should be like a tree array system, something more organized such as the following code :
let data2 = [{
    KlasCode: "AA",
    Modules: [
      {
      ModuleID: "1061",
      Participation: [{
          ParticipationLetterCode: "Y",
          LESDatum: "06/02/2017",
          LESID: "1"
        },
        {
          ParticipationLetterCode: "X",
          LESDatum: "07/02/2017",
          LESID: "2"
        }
      },
       {
          ModuleID: "1062",
          Participation:[{
          ParticipationLetterCode: "Z",
          LESDatum: "13/02/2017",
          LESID: "3"
                         }]
        }

    }]
  },
  {
    KlasCode: "BB",
    Modules: [{
      ModuleID: "1063",
      Participation: [{
        ParticipationLetterCode: "x",
        LESDatum: "6/02/2017",
        LESID: "4"
      }]

    }]
  }

]

【问题讨论】:

  • 应该是 AA 抱歉,我更新了东西 thx。我试图结合 .map() 和 _gropuby。没有运气
  • 这有帮助吗?

标签: javascript arrays vue.js lodash syncfusion


【解决方案1】:

创建了一个函数来做同样的事情,希望这会有所帮助-:

const custommodifier = (data) => Object.values(data.reduce((acc,{KlasCode, ModuleID, ...participationData}) => {
    if(acc[KlasCode]){
        acc[KlasCode].Modules[0].Participation.push({
            ...participationData
        })
    }
    else {
        acc[KlasCode] = {
            KlasCode,
            Modules: [{
                ModuleID,
                Participation: [{
                    ...participationData
                }]
            }]
        }
    }
    return acc;
}, {}));


let data = [{
    KlasCode: "AA",
    LESDatum: "06/02/2017",
    LESID: "1",
    ModuleID: "1061",
    ParticipationLetterCode: "Y"
  }, {
    KlasCode: "AA",
    LESDatum: "07/02/2017",
    LESID: "2",
    ModuleID: "1061",
    ParticipationLetterCode: "X",
  },
  {
    KlasCode: "AA",
    LESDatum: "13/02/2017",
    LESID: "3",
    ModuleID: "1061",
    ParticipationLetterCode: "Z"
  },
  {
    KlasCode: "BB",
    LESDatum: "16/02/2017",
    LESID: "4",
    ModuleID: "1062",
    ParticipationLetterCode: "X"
  }
]
console.log(custommodifier(data))

【讨论】:

【解决方案2】:

您可以采用动态方法,使用一组键广告组名称,然后从实际对象中取出键。最后,构建嵌套组后,将最终对象添加到最后一个组。

如有必要,此方法适用于更多嵌套组。

let data = [{ KlasCode: "AA", LESDatum: "06/02/2017", LESID: "1", ModuleID: "1061", ParticipationLetterCode: "Y" }, { KlasCode: "AA", LESDatum: "07/02/2017", LESID: "2", ModuleID: "1061", ParticipationLetterCode: "X" }, { KlasCode: "AA", LESDatum: "13/02/2017", LESID: "3", ModuleID: "1061", ParticipationLetterCode: "Z" }, { KlasCode: "BB", LESDatum: "16/02/2017", LESID: "4", ModuleID: "1062", ParticipationLetterCode: "X" }],
    groups = [['KlasCode', 'Modules'], ['ModuleID', 'Participation']],
    result = data.reduce((r, o) => {
        groups
            .reduce((p, [key, group]) => {
                let value, temp;
                ({ [key]: value, ...o } = o);
                temp = p.find(q => q[key] === value);
                if (!temp) p.push(temp = { [key]: value, [group]: [] });
                return temp[group];
            }, r)
            .push(o);
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案3】:

    我会使用groupBy 函数和Object.entries。您将需要使用它两次,以处理您的两个级别的分组。

    您可以使用来自 lodash 的groupBy(或者来自 Ramda 的那个,或者其他任何地方),或者这里包含的简单的那个。

    const groupBy = (fn) => (xs) => 
      xs .reduce((a, x) => ({... a, [fn(x)]: [... (a [fn (x)] || []), x]}), {})
    
    const transform = (data) => Object.entries (groupBy (x => x.KlasCode) (data))
      .map(([KlasCode, Modules]) => ({
        KlasCode, 
        Modules: Object.entries(groupBy (x => x.ModuleID) (Modules))
          .map(([ModuleID, Participations]) => ({
            ModuleID,
            Participation: Participations.map (({ParticipationLetterCode, KlasCode, ...rest}) => rest)
          })
        )
      }))
    
    let data1 = [{KlasCode: "AA", LESDatum: "06/02/2017", LESID: "1", ModuleID: "1061", ParticipationLetterCode: "Y"}, {KlasCode: "AA", LESDatum: "07/02/2017", LESID: "2", ModuleID: "1061", ParticipationLetterCode: "X"}, {KlasCode: "AA", LESDatum: "13/02/2017", LESID: "3", ModuleID: "1062", ParticipationLetterCode: "Z"}, {KlasCode: "BB", LESDatum: "16/02/2017", LESID: "4", ModuleID: "1063", ParticipationLetterCode: "X"}]
    
    console .log (transform (data1))
    .as-console-wrapper {min-height: 100% !important; top: 0}

    更新——Ramda 替代方案

    我对上述解决方案和这里的其他答案并不感到兴奋。有时发生这种情况时,我会在 Ramda 中重写(免责声明:我是它的作者之一),然后将涉及的 Ramda 函数移植到 vanilla JS 中。这次我不打算做后者,但我将分享我如何利用像 Ramda 这样的库来做到这一点。我猜lodash中也有类似的功能。

    const groupByProp = (propName, childName) => pipe (
      groupBy (prop (propName)),
      toPairs,
      map (evolve ([ , map (dissoc (propName))])),
      map (zipObj ([propName, childName]))
    )
    
    const transform = pipe (
      groupByProp('KlasCode', 'Modules'),
      map (evolve ({Modules: groupByProp('ModuleID', 'Participation')}))
    )
    
    let data1 = [{KlasCode: "AA", LESDatum: "06/02/2017", LESID: "1", ModuleID: "1061", ParticipationLetterCode: "Y"}, {KlasCode: "AA", LESDatum: "07/02/2017", LESID: "2", ModuleID: "1061", ParticipationLetterCode: "X"}, {KlasCode: "AA", LESDatum: "13/02/2017", LESID: "3", ModuleID: "1062", ParticipationLetterCode: "Z"}, {KlasCode: "BB", LESDatum: "16/02/2017", LESID: "4", ModuleID: "1063", ParticipationLetterCode: "X"}]
    
    console .log (transform (data1))
    .as-console-wrapper {min-height: 100% !important; top: 0}
    <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
    <script> const {groupBy, prop, toPairs, map, evolve, dissoc, zipObj, pipe} = R </script>

    我觉得这些功能似乎更简单,更好地展示了转换的步骤。但这还不足以成为包含库的理由。但是一旦你遇到了一些这样的情况,图书馆似乎就很有意义了。

    我并不是要在这里推 Ramda,只是要指出,当您拥有实用程序库的工具时,您通常可以编写更简单的代码。

    【讨论】:

    猜你喜欢
    • 2020-09-29
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    相关资源
    最近更新 更多