将一个数组从一个平面的一维数组转换为一个树状数组,就像在javascriptlodash中一样。

问题描述 投票:0回答:1

我有一个问题,要把下面的数组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"
      }]

    }]
  }

]
javascript arrays vue.js lodash syncfusion
1个回答
2
投票

创建了一个函数来做同样的事情,希望对你有帮助-。

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))

1
投票

你可以用一个动态的方法,用一个键和组名的数组,然后从实际的对象中取出键。最后,在建立嵌套组后,将最终对象添加到最后一个组中。

如果有必要,这种方法适用于更多的嵌套组。

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; }

1
投票

我会使用一个 groupBy 函数,再配合使用一下 Object.entries. 你将需要使用它两次,以处理你的两个级别的分组。

你可以使用 groupBy 从lodash(或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,只是想指出,当你有实用库的工具可以使用时,你往往可以写出更简单的代码。

© www.soinside.com 2019 - 2024. All rights reserved.