【问题标题】:Lodash: Convert array with duplicate values to object with number of repeated occurrencesLodash:将具有重复值的数组转换为具有重复出现次数的对象
【发布时间】:2016-08-30 16:07:17
【问题描述】:

这是我的数组:

['California','Texas','Texas','Texas','New York','Missouri','New Mexico','California']

lodash 中是否有办法将其转换为具有重复出现次数的对象,如下所示:

[
    {'name':'California', 'count':2},
    {'name':'Texas', 'count':3},
    {'name':'New York', 'count':1},
    {'name':'Missouri', 'count':1},
    {'name':'New Mexico', 'count':1},
]

我尝试了很多组合,但都没有成功。文档:https://lodash.com/docs#countBy

【问题讨论】:

  • 你试过什么?在我看来countBy 有效,您只需在完成后稍微修改结果
  • 既然你只有两个属性,也许{California: 2, Texas: 3} 会更好——只是一个建议

标签: javascript arrays object underscore.js lodash


【解决方案1】:

你可以只映射_.countBy的结果。

var array = ['California','Texas','Texas','Texas','New York','Missouri','New Mexico','California'],
    count = _.countBy(array),
    result = _.map(count, (v, k) => ({ name: k, count: v }));

console.log(count);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

结合_.chain

var array = ['California','Texas','Texas','Texas','New York','Missouri','New Mexico','California'],
    count = _
        .chain(array)
        .countBy()
        .map((v, k) => ({ name: k, count: v }));

console.log(count);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

【讨论】:

  • 如果你 _.chain 调用,它的性能会稍微好一点,因为你不需要中间值。它也使代码看起来更整洁(同样 - 没有中间值)。 _.reduce 可能更适合这种事情。
  • 感谢 Lodash 的解决方案!请注意,上面的变量“k”和“v”需要切换。否则它会说: { name:3, count:'Texas' }
【解决方案2】:

您可以通过reduce() 做到这一点

var ar = ['California','Texas','Texas','Texas','New York','Missouri','New Mexico','California'];

var obj = {}
var result = ar.reduce(function(r, e) {
  if(!obj[e]) {
    obj[e] = {name: e, count: 0};
    r.push(obj[e])
  }
  obj[e].count++;
  return r;
}, [])

console.log(result)

【讨论】:

    【解决方案3】:

    我不确定是否有内置函数可以实现,但您可以使用标准方法来实现。

    var arr = ['California', 'Texas', 'Texas', 'Texas', 'New York', 'Missouri', 'New Mexico', 'California'];
    var obj = [];
    
    arr.forEach(a => {
        var b = obj.find(b => b.name == a);
        if(!b){
            obj.push({
                name: a,
                count: 1
            });
        }else{
            b.count++;
        }
    });
    
    console.log(JSON.stringify(obj, null, 2));
    

    【讨论】:

    • 您可以使用find 代替filter。更准确地说是您想要的。
    • @Vld 更新答案。
    【解决方案4】:

    正如你所说,有 countBy 函数,你必须映射结果以根据需要设置格式:

    var result = _( array )
      .countBy( )
      .map( ( key, value ) => ( { name: key, count: value } ) )
      .value( )
    
    console.log( result );
    

    【讨论】:

    • OP 已经提到了。此外,您不需要第二个参数 - 它默认为相同。
    • 对,我没注意,到时候更新答案
    【解决方案5】:

    两行纯 JS。

    var arr = ['California','Texas','Texas','Texas','New York','Missouri','New Mexico','California'],
        lut = arr.reduce((p,c) => p[c] ? (p[c]++ ,p) : (p[c] = 1, p),{});
     result = Object.keys(lut).map(k => ({name:k,count:lut[k]}));
    console.log(result);

    【讨论】:

      【解决方案6】:

      在纯 Javascript 中,您可以使用 Array#forEach

      var data = ['toString', 'California', 'Texas', 'Texas', 'Texas', 'New York', 'Missouri', 'New Mexico', 'California'],
          count = [];
      
      data.forEach(function (a) {
          if (!this[a]) {
              this[a] = { name: a, count: 0 };
              count.push(this[a]);
          }
          this[a].count++;
      }, Object.create(null));
      
      console.log(count)
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      带有{}的版本

      var data = ['toString', 'California', 'Texas', 'Texas', 'Texas', 'New York', 'Missouri', 'New Mexico', 'California'],
          count = [];
      
      data.forEach(function (a) {
          if (!this[a]) {
              this[a] = { name: a, count: 0 };
              count.push(this[a]);
          }
          this[a].count++;
      }, {}); // no Object.create(null)!
      
      console.log(count)
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      【讨论】:

      • 加入你的答案或者删除这个会更好。
      • 你使用Object.create(null)而不仅仅是{}是有原因的
      • @NenadVracar,你可以数数 toString,如果没有一个真正的空对象,那是行不通的。
      • @NinaScholz 使用{} 创建的对象的唯一属性是__proto__。函数toString实际上是{}.__proto__.constructor.prototype的属性。
      • @SoftwareEngineer171,请注意示例一和示例二的区别。关注toString
      猜你喜欢
      • 2023-03-04
      • 2021-10-24
      • 2014-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-28
      • 2021-09-29
      • 2021-08-22
      相关资源
      最近更新 更多