【问题标题】:reduce array of array into a flat array of object将数组数组减少为对象的平面数组
【发布时间】:2021-04-05 23:14:24
【问题描述】:

我一直在转换数据结构:

let d = [
  { no: 1, score: 7000 },
  { no: 2, score: 10000 },
  [
    { no: 1, score: 8500 },
    { no: 2, score: 6500 }
  ]
];

    
d = d.reduce((accum, o) => {
   
}, [])

我怎样才能制作这个?

[{name: 'no 1', score: [7000, 8500]}, {name: 'no 2', score: [10000, 6500]}]

【问题讨论】:

标签: javascript arrays typescript ecmascript-6


【解决方案1】:

在您的情况下,您不仅需要展平列表,还需要按no 属性分组。

对于扁平化,您可以使用Array.prototype.flat()。这是一个相当新的功能,所以如果你不使用 polyfill,你可能无法使用它。所以你可以检查alternative 的实现。

对于分组,你可以reduce到key为no属性的对象。请注意,如果存在多个no 属性,则需要保存一个包含所有score 值的数组。

例子:

const d = [{ no: 1, score: 7000 },
    { no: 2, score: 10000 },
   [ { no: 1, score: 8500 },
    { no: 2, score: 6500 }]]


const grouped = d.flat().reduce((prev, cur) => {
    if (cur.no in prev) {
        prev[cur.no].score.push(cur.score)
    } else {
        prev[cur.no] = {
            name: 'no ' + cur.no,
            score: [cur.score]
        }
    }
    return prev
}, {})

console.log(Object.values(grouped))

在示例中,我们使用了修改。可以在不修改的情况下执行此操作 - 在每次缩减迭代期间返回一个新副本。但是,根据阵列大小,可能会出现性能问题。此外,进行修改是安全的,因为在这种情况下我们会创建一个新对象。

【讨论】:

    【解决方案2】:

    试试这个:

    let d = [
        { no: 1, score: 7000 },
        { no: 2, score: 10000 },
        [
            { no: 1, score: 8500 },
            { no: 2, score: 6500 }
        ]
    ]
    
    
    const reducer = (arr, start = []) => arr.reduce((acc, next) => {
        if (Array.isArray(next)) return reducer(next, acc);
        for (const value of acc) {
            if (value.name === `no ${next.no}`) {
                value.score = [...value.score, next.score];
                return acc;
            }
        }
        
        return [...acc, {
            name: `no ${next.no}`,
            score: [next.score]
        }];
    }, start);
    
    console.log(reducer(d));
    

    【讨论】:

      【解决方案3】:

      您可以使用Array.prototype.flat()

      或者如果你有任何类似的数组,

      let d = [
        { no: 1, score: 7000 },
        { no: 2, score: 10000 },
        [
          { no: 1, score: 8500 },
          { no: 2, score: 6500 }
        ]
      ];
      

      然后使用d.flat()

      【讨论】:

        【解决方案4】:

        这是使用简单的reduce 的一种方法,

        const result = d.flat().reduce((acc: {name: string, score: number[]}[], curr) => {
          const { no, score } = curr;
          let item = acc.find(a => a.name === `no ${no}`);
          if (!item) {
            item = { name: `no ${no}`, score: []};
            acc.push(item);
          }
        
          item.score.push(score);
          return acc;
            
        }, []);
        
        console.log(result)
        

        【讨论】:

        • 最简单的解决方案,干净。谢谢!
        • @NadielyJade 请注意,flat 期望作为参数 depth(默认为 1)。所以如果你知道数组的深度,上面的解决方案是完美的。如果深度未知,则需要递归调用 reducer。
        【解决方案5】:

        您可以采用动态方法,按给定键分组,并将所有其他属性用于新数组。

        const
            groupBy = key => (r, value) => {
                if (Array.isArray(value)) return value.reduce(group, r);
                const { [key]: _, ...o } = value;
                Object.entries(o).forEach(([k, v]) => ((r[_] ??= { [key]: _ })[k] ??= []).push(v));
                return r;
            }
            data = [{ no: 1, score: 7000 }, { no: 2, score: 10000 }, [{ no: 1, score: 8500 }, { no: 2, score: 6500 }]],
            group = groupBy('no'),
            result = Object.values(data.reduce(group, {}));
        
        console.log(result);
        .as-console-wrapper { max-height: 100% !important; top: 0; }

        【讨论】:

          【解决方案6】:

          这是一个简洁的打字稿功能解决方案,因为您包含了标签-

          const arr = [
              { no: 1, score: 7000 },
              { no: 2, score: 10000 },
              [
                  { no: 1, score: 8500 },
                  { no: 2, score: 6500 },
              ],
          ];
          
          const result = Object.entries(
              arr.flat().reduce((accum: { [key: number]: number[] }, el: { no: number; score: number }) => {
                  accum[el.no] = (accum[el.no] ?? []).concat(el.score);
                  return accum;
              }, {})
          ).map(([num, scores]) => ({ no: Number(num), scores: scores }));
          
          console.log(result);
          

          结果-

          [
            { no: 1, scores: [ 7000, 8500 ] },
            { no: 2, scores: [ 10000, 6500 ] }
          ]
          

          这首先使用Array.prototype.flat 将内部数组展平。然后它使用reduce 构造一个对象,其中no 值作为键,score 值作为值数组。

          最后,reduce 导致{ 1: [7000, 8500], 2: [10000, 6500] } - 使用Object.entries 将其转换为条目以获得[['1', [7000, 8500]], ['2', [10000, 6500]]]

          最后,映射条目以将['1', [7000, 8500]] 格式转换为{ no: 1, scores: [ 7000, 8500 ] } 格式,您就完成了!

          【讨论】:

            【解决方案7】:

            Array.prototype.flat()在实际分组之前调用,然后使用reduce函数创建结果。

            let d = [{
                no: 1,
                score: 7000
            },
            {
                no: 2,
                score: 10000
            },
            [{
                    no: 1,
                    score: 8500
                },
                {
                    no: 2,
                    score: 6500
                }
            ]
            ]
            
            const result = d.flat().reduce((result, element) => {
            const key = element.no;
            if (!result[key]) {
                result[key] = {
                    name: `no ${key}`,
                    score: []
                }
            }
            
            result[key].score.push(element.score);
            return result;
            }, {})
            console.log(Object.values(result))

            【讨论】:

              【解决方案8】:

              let d = [{ no: 1, score: 7000 },
                  { no: 2, score: 10000 },
                 [ { no: 1, score: 8500 },
                  { no: 2, score: 6500 }]]
                  
                  const result=d.flat().reduce((acc,curr)=>{
                  if(acc[curr.no]){
                    acc[curr.no].score.push(curr.score)
                  } else {
                    const keys=Object.keys(curr)
                    acc[curr.no]={ name: keys[0]+ ' '+curr.no, score:[curr.score]}
                  }
                  return acc;
                  },{})
              console.log(Object.values(result))

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-03-26
                • 2018-02-14
                • 2017-08-17
                • 2020-01-15
                • 1970-01-01
                相关资源
                最近更新 更多