【问题标题】:count repeated array of object property to produce a new array计算对象属性的重复数组以生成新数组
【发布时间】:2019-08-23 11:11:35
【问题描述】:

我有这个对象数组

[{
    tag: 'james'
  },
  {
    tag: 'james'
  },
  {
    tag: 'john'
  }
]

如何计算并生成如下所示的新数组?

[{
  tag: 'james',
  count: 2
}, {
  tag: 'john',
  count: 1
}]

我尝试使用 reduce 生成的对象而不是对象数组。

const arr = [{tag: 'james'},{tag: 'james'},{tag: 'john'}];
let newArr = arr.reduce((accum, arr) => {
  accum[arr.tag] = ++accum[arr.tag] || 1
  return accum
}, {})

console.log(newArr)

【问题讨论】:

    标签: javascript arrays reactjs object ecmascript-6


    【解决方案1】:

    创建一个对象而不是数字,最后使用Object.values 方法从对象中获取这些值。

    // just extract values from the object as an array
    let res = Object.values(arr.reduce((accum, o) => {
      // initialize object if not defined already
      accum[o.tag] = accum[o.tag] || { ...o, count: 0  }
      // increment count property
      accum[o.tag].count++;
      return accum
    }, {}))
    

    let arr = [{tag: 'james'},{tag: 'james'},{tag: 'john'}]
    
    let res = Object.values(arr.reduce((accum, o) => {
      accum[o.tag] = accum[o.tag] || { ...o, count: 0 }
      accum[o.tag].count++;
      return accum
    }, {}))
    
    console.log(res)


    您甚至可以通过使用附加变量进行对象/索引引用来直接创建数组。
    // an object for keeping reference 
    let ref = {};
    
    let res = arr.reduce((accum, o) => {
      // check reference already defined, if not define refernece and push to the array
      ref[o.tag] || accum.push(ref[o.tag] = { ...o, count: 0 })
      // update count using the refernece keeped in the object
      ref[o.tag].count++;
      return accum
    }, []);
    

    let arr = [{tag: 'james'},{tag: 'james'},{tag: 'john'}]
    
    let ref = {};
    
    let res = arr.reduce((accum, o) => {
      ref[o.tag] || accum.push(ref[o.tag] = { ...o, count: 0 })
      ref[o.tag].count++;
      return accum
    }, []);
    
    console.log(res)

    【讨论】:

      【解决方案2】:

      您快到了,但您需要从对象中取出键和值并构建一个新数组。

      var array = [{ tag: 'jane' }, { tag: 'jane' }, { tag: 'john' }],
          result = Object
              .entries(
                  array.reduce((accum, { tag }) => {
                      accum[tag] = (accum[tag] || 0) + 1;
                      return accum;
                  }, {}))
              .map(([tag, count]) => ({ tag, count }));
      
      console.log(result);
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      【讨论】:

      • 为什么是地图?来自Balan的那个似乎更简单let res = Object.values(arr.reduce((accum, o) => { accum[o.tag] = accum[o.tag] || { ...o, count: 0 } accum[o.tag].count++; return accum }, {}))
      • 我的解决方案保持开销小(和抽象)并构建最终对象,其中提到的代码直接构建最终对象作为对象的值。这看起来像是一个品味问题。
      【解决方案3】:

      首先测试对象是否不存在 - 如果不存在,则创建一个。然后加入累加器。还要注意你想要一个数组,所以使用[] 而不是{} 作为累加器值:

      const data = [{
          tag: 'james'
        },
        {
          tag: 'james'
        },
        {
          tag: 'john'
        }
      ];
      
      const grouped = data.reduce((acc, { tag }) => {
        if (!acc.some(e => e.tag == tag)) {
          acc.push({ tag, count: 0 });
        }
        acc.find(e => e.tag == tag).count++;
        return acc;
      }, []);
      
      console.log(grouped);
      .as-console-wrapper { max-height: 100% !important; top: auto; }

      【讨论】:

        【解决方案4】:

        更简单的代码是:

        const arr = [{
            tag: 'james'
          },
          {
            tag: 'james'
          },
          {
            tag: 'john'
          },
          {
            tag: 'lewis'
          },
          {
            tag: 'john'
          }
        ]
        
        const counts = arr.reduce((acc, cv) => {
          const val = acc.find(t => t.tag == cv.tag)
          if (val) {
            val.count++
            acc.push(val)
            return acc
          }
          cv.count = 1
          acc.push(cv)
          return acc
        }, [])
        
        console.log(counts)

        【讨论】:

          【解决方案5】:

          你的直觉很好,你很接近;我建议你一个更通用的答案

          const groupTags = data => field => Object.values(data.reduce((acc, o) =>
          ({...acc,
            [o[field]]: {
              [field]: o[field],
              count: acc[o[field]] ? acc[o[field]].count + 1 : 1 
            }
          }), {}))
          

          你可以像这样使用它

          groupTags(data)("tag")
          

          【讨论】:

            【解决方案6】:
            //simple approach using forEach method
            
            let lists = [{tag: 'james'},{tag: 'james'},{tag: 'john'}]; 
            const finalOutput = [];
            const tempStore = {};
            
            lists.forEach((list) => {
                  tempStore[list.tag] = (tempStore[list.tag] == undefined) ? 1: tempStore[list.tag]+1;
                  const index = finalOutput.findIndex(e => e.tag == list.tag);
                  if(index > -1) {
                    finalOutput[index] = {tag: list.tag, count: tempStore[list.tag]}
                  }
                  else 
                    finalOutput.push({tag: list.tag, count: tempStore[list.tag]})
            });
            
            console.log(finalOutput);
            

            【讨论】:

              猜你喜欢
              • 2021-01-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-01-11
              • 1970-01-01
              • 2022-01-08
              • 1970-01-01
              相关资源
              最近更新 更多