代码之家  ›  专栏  ›  技术社区  ›  Boky

使用lodash进行分组

  •  1
  • Boky  · 技术社区  · 8 年前

    我有一个对象数组,如下所示:

    var data = [
      {
        "count": 1, 
        "make": "ALFA ROMEO", 
        "model": "GIULIETTA DIESEL - 2010"
      }, 
      {
        "count": 2, 
        "make": "AUDI", 
        "model": "A1 DIESEL"
      }, 
      {
        "count": 1, 
        "make": "AUDI", 
        "model": "A1 SPORTBACK DIESEL"
      }, 
      {
        "count": 2, 
        "make": "AUDI", 
        "model": "A3 DIESEL - 2012"
      }, 
      {
        "count": 3, 
        "make": "Volkswagen", 
        "model": "Golf"
      }, 
      {
        "count": 3, 
        "make": "Ford", 
        "model": "Escord"
      }, 
      {
        "count": 2, 
        "make": "Opel", 
        "model": "Zafira"
      }
    ]
    

    我想 group by 它由 make 然后得到三个最高计数,其余我将显示其他。

    var result = [
        {
           "brand": "Audi",
           "count": 5
         },
         {
           "brand": "Volkswagen",
           "count": 3
         },
         {
           "brand": "Ford",
           "count": 3
         },
         {
           "brand": "Other",
           "count": 3
         }
    ]
    

    我不知道怎么开始。有什么帮助吗?

    3 回复  |  直到 8 年前
        1
  •  3
  •   scx    8 年前

    你可以用lodash的组合来实现这一点 groupBy sumBy

    var result = _.chain(data)
            .groupBy("make")
            .map( (element, id) => ({
                make: id,
                count: _.sumBy(element, 'count'),
            }))
            .value();
    
    console.log(result);
    
    [
      {
        "make": "ALFA ROMEO",
        "count": 1
      },
      {
        "make": "AUDI",
        "count": 5
      },
      {
        "make": "Volkswagen",
        "count": 3
      },
      {
        "make": "Ford",
        "count": 3
      },
      {
        "make": "Opel",
        "count": 2
      }
    ]
    
        2
  •  2
  •   Ori Drori    8 年前

    使用lodash

    启动lodash链。使用 _.groupBy() 那么按惯例 _.map() 结果,以及 _.sumBy() 这个 count 属性。使用转换回数组 _.values() ,按降序排序 _.orderBy() ,并使用 _.value() 完成链条。 Split 将结果分成2个数组,并使用reduce对第2个数组(低集计数)求和:

    var data = [{"count":1,"make":"ALFA ROMEO","model":"GIULIETTA DIESEL - 2010"},{"count":2,"make":"AUDI","model":"A1 DIESEL"},{"count":1,"make":"AUDI","model":"A1 SPORTBACK DIESEL"},{"count":2,"make":"AUDI","model":"A3 DIESEL - 2012"},{"count":3,"make":"Volkswagen","model":"Golf"},{"count":3,"make":"Ford","model":"Escord"},{"count":2,"make":"Opel","model":"Zafira"}];
    
    var counts = _(data)
      .groupBy('make')
      .map(function(g, key) { return {
          make: key,
          count: _.sumBy(g, 'count')
      };})
      .values()
      .orderBy('count', 'desc')
      .value();
      
    var result = counts.slice(0, 3).concat({
      brand: 'other',
      count: counts.slice(3).reduce(function(s, { count }) { return s + count; }, 0)
    })
      
    console.log(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

    使用ES6

    使用迭代 Array#reduce ,将所有生成计数值收集到 Map ,然后获取 map values iterator spread 获取数组,并按降序排序。 分裂 将结果分成2个数组,并使用reduce对第2个数组(低集计数)求和:

    const data = [{"count":1,"make":"ALFA ROMEO","model":"GIULIETTA DIESEL - 2010"},{"count":2,"make":"AUDI","model":"A1 DIESEL"},{"count":1,"make":"AUDI","model":"A1 SPORTBACK DIESEL"},{"count":2,"make":"AUDI","model":"A3 DIESEL - 2012"},{"count":3,"make":"Volkswagen","model":"Golf"},{"count":3,"make":"Ford","model":"Escord"},{"count":2,"make":"Opel","model":"Zafira"}];
    
    const counts = [...data.reduce((m, { make, count }) => {
      const item = m.get(make) || { make, count: 0 };
      
      item.count += count;
    
      return m.set(make,  item);
    }, new Map()).values()].sort((a, b) => b.count - a.count);
    
    const result = counts.slice(0, 3).concat({
      brand: 'other',
      count: counts.slice(3).reduce((s, { count }) => s + count, 0)
    })
    
    console.log(result);
        3
  •  1
  •   Nina Scholz    8 年前

    使用纯Javascript,您可以使用哈希表来收集相同的内容 make 并对结果数组排序。稍后添加结果集末尾的所有计数,直到数组获得所需的长度。

    var data = [{ count: 1, make: "ALFA ROMEO", model: "GIULIETTA DIESEL - 2010" }, { count: 2, make: "AUDI", model: "A1 DIESEL" }, { count: 1, make: "AUDI", model: "A1 SPORTBACK DIESEL" }, { count: 2, make: "AUDI", model: "A3 DIESEL - 2012" }, { count: 3, make: "Volkswagen", model: "Golf" }, { count: 3, make: "Ford", model: "Escord" }, { count: 2, make: "Opel", model: "Zafira" }],
        hash = Object.create(null),
        result = [];
    
    data.forEach(function (car) {
        if (!hash[car.make]) {
            hash[car.make] = { make: car.make, count: 0 };
            result.push(hash[car.make]);
        }
        hash[car.make].count += car.count;
    });
    
    result.sort(function (a, b) {
        return b.count - a.count;
    });
    
    while (result.length > 4) {
        result.push({ make: 'Other', count: result.pop().count + result.pop().count });
    }
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }