【问题标题】:How do we reduce nested arrays?我们如何减少嵌套数组?
【发布时间】:2019-11-20 17:52:28
【问题描述】:

我将学生 ID 与分数映射的对象如下:

[
    {id: 111, marks: [{sub: 'eng', mark: 90}, {sub: 'maths', mark: 20}]},
    {id: 222},
    {id: 333, marks: []},
    {id: 444, marks: [{sub: 'eng', mark: 70}]}
]

我想将其减少如下:

{
    marks[0]: "0:eng:90", // studentIndex:subject_name:mark
    marks[1]: "0:maths:20",
    marks[2]: "3:eng:70"
}

在上面的结果中,键是“marks[]”,值是一个字符串,它是studentIndex、主题和标记的串联。 所以这里的 0:eng:90 表示索引为 0 的学生在英语科目中获得了 90 分

我正在使用 lodash,我尝试了以下方法:

reduce(studentList, (acc, student, studentIndex) => {
    map(get(student, 'marks'), (marks) => {
      acc[`marks[${keys(acc).length}]`] = `${studentIndex}:${marks.sub}:${marks.mark}`;
    });
    return acc;
  }, {});

还有其他更好的方法吗?

【问题讨论】:

    标签: javascript arrays object ecmascript-6 lodash


    【解决方案1】:

    没有 Lodash

    var studentList = [{"id":111,"marks":[{"sub":"eng","mark":90},{"sub":"maths","mark":20}]},{"id":222},{"id":333,"marks":[]},{"id":444,"marks":[{"sub":"eng","mark":70}]}]
    
    var result = studentList.reduce((acc, student, studentIndex) => {
      (student.marks || []).map((marks) => {
        acc[`marks[${Object.keys(acc).length}]`] = `${studentIndex}:${marks.sub}:${marks.mark}`;
      });
      return acc;
    }, {});
    
    console.log(result)

    使用 Lodash

    var studentList = [{"id":111,"marks":[{"sub":"eng","mark":90},{"sub":"maths","mark":20}]},{"id":222},{"id":333,"marks":[]},{"id":444,"marks":[{"sub":"eng","mark":70}]}]
    
    var result = _.reduce(studentList, (acc, student, studentIndex) => {
      _.map(student.marks || [], (marks) => {
        acc[`marks[${_.keys(acc).length}]`] = `${studentIndex}:${marks.sub}:${marks.mark}`;
      });
      return acc;
    }, {});
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

    【讨论】:

    • 谢谢,我也试过了。 reduce 中的映射和使用键计算的索引。只是想知道是否有更好的方法来计算它。
    • @DeepaSajaniJeyaraj 我认为没有更好的方法来使用reduce
    【解决方案2】:

    你可以使用forEach循环。

    const input = [
        {id: 111, marks: [{sub: 'eng', mark: 90}, {sub: 'maths', mark: 20}]},
        {id: 222, marks: []},
        {id: 333, marks: []},
        {id: 444, marks: [{sub: 'eng', mark: 70}]}
    ];
    
    const output = [];
    
    input.forEach(({marks}, i) =>  {
        marks.forEach(({sub, mark}) => {
            output.push(`${i}:${sub}:${mark}`);
        });
    });
    
    console.log(output);

    --编辑--

    const input = [
        {id: 111, marks: [{sub: 'eng', mark: 90}, {sub: 'maths', mark: 20}]},
        {id: 222},
        {id: 333, marks: []},
        {id: 444, marks: [{sub: 'eng', mark: 70}]}
    ];
    
    const output = {};
    let count = 0;
    
    input.forEach((obj, i) =>  {
        if(obj.hasOwnProperty("marks")) {
            obj.marks.forEach(({sub, mark}) => {
                output[`marks[${count}]`] = `${i}:${sub}:${mark}`;
                count++;
            });
        }
    });
    
    console.log(output);

    【讨论】:

    • 谢谢,但这会返回一个数组而不是一个对象。响应应该是一个键值对'marks[0]: "0:eng:90"'。此外,当没有标记属性时,这会中断。
    • @DeepaSajaniJeyaraj - 见编辑。您可以添加对marks 属性的检查。
    【解决方案3】:

    使用map 的另一种不带lodash 的更短方法:

    var studentList = [
        {id: 111, marks: [{sub: 'eng', mark: 90}, {sub: 'maths', mark: 20}]},
        {id: 222},
        {id: 333, marks: []},
        {id: 444, marks: [{sub: 'eng', mark: 70}]}
    ];
    
    var ac = {};
    studentList.map((student, i) => {
      if (student.marks && student.marks.length)
        student.marks.map(m => ac[`marks[${Object.keys(ac).length}]`] = `${i}:${m.sub}:${m.mark}`);
    });
    
    console.log(ac);

    【讨论】:

      【解决方案4】:

      使用 lodash,您可以使用 _.flatMap()map 将学生的分数迭代为 [key, value] 对。要生成密钥,您可以使用_.uniqueId()。最终结果将是一个对数组,您可以使用 _.fromPairs() 将其转换为对象:

      const studentList = [{"id":111,"marks":[{"sub":"eng","mark":90},{"sub":"maths","mark":20}]},{"id":222},{"id":333,"marks":[]},{"id":444,"marks":[{"sub":"eng","mark":70}]}]
      
      const result = _.fromPairs( // convert the array to an object
        _.flatMap(studentList, ({ marks }, sIndex) => // iterate the students
          _.map(marks, ({ sub, mark }) => [ // iterate the marks
            `marks${_.uniqueId() - 1}`, // generate the key
            `${sIndex}:${sub}:${mark}` // generate the value
          ])
        )
      )
      
      console.log(result)
      <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-12
        • 2018-05-30
        • 2019-12-21
        • 1970-01-01
        • 2020-02-07
        • 1970-01-01
        相关资源
        最近更新 更多