简体   繁体   English

对象数组,按对象键分组:值

[英]Array of objects, group by object key:value

I have an array of objects like this: 我有一个这样的对象数组:

const data = [
      { id: 1, type: { name: "A" }, condition: "new" },
      { id: 2, type: { name: "C" }, condition: "broken" },
      { id: 3, type: { name: "C" }, condition: "brand new" },
      { id: 4, type: { name: "B" }, condition: "broken" },
      { id: 5, type: { name: "C" }, condition: "brand new" },
      { id: 6, type: { name: "A" }, condition: "new" },
      { id: 7, type: { name: "A" }, condition: "new" },
      { id: 8, type: { name: "B" }, condition: "broken" },
      { id: 9, type: { name: "C" }, condition: "broken" }
    ];

What i'm trying to do is to group those objects by type's key:value in this case by name:value , like this: 我想做的是按类型的key:value将这些对象分组,在这种情况下,按name:value进行分组,如下所示:

const data = [
      {
        by: {
          type: { name: "A" }
        },
        chunks: [
          { id: 1, type: { name: "A" }, condition: "new" },
          { id: 6, type: { name: "A" }, condition: "new" },
          { id: 7, type: { name: "A" }, condition: "new" }
        ]
      },
      {
        by: {
          type: { name: "C" }
        },
        chunks: [
          { id: 2, type: { name: "C" }, condition: "broken" },
          { id: 3, type: { name: "C" }, condition: "brand new" },
          { id: 5, type: { name: "C" }, condition: "brand new" },
          { id: 9, type: { name: "C" }, condition: "broken" }
        ]
      },
      {
        by: {
          type: { name: "B" }
        },
        chunks: [
          { id: 4, type: { name: "B" }, condition: "broken" },
          { id: 8, type: { name: "B" }, condition: "broken" }
        ]
      },
    ];

I've tried to use lodash and Array.prototype.reduce() , my last attempt was using lodash, but i can't get the type as object. 我尝试使用lodash和Array.prototype.reduce() ,我的最后一次尝试是使用lodash,但我无法将类型作为对象。

_.chain(channels)
      .groupBy("type.name")
      .map((item, i) => {
        return {
          chunks: item,
          by: i
        };
      })
      .value();

You can use a Map to collect the data by group, and then its values() method will iterate the data as you want: 您可以使用Map按组收集数据,然后其values()方法将根据需要迭代数据:

 const data = [{ id: 1, type: { name: "A" }, condition: "new" },{ id: 2, type: { name: "C" }, condition: "broken" },{ id: 3, type: { name: "C" }, condition: "brand new" },{ id: 4, type: { name: "B" }, condition: "broken" },{ id: 5, type: { name: "C" }, condition: "brand new" },{ id: 6, type: { name: "A" }, condition: "new" },{ id: 7, type: { name: "A" }, condition: "new" },{ id: 8, type: { name: "B" }, condition: "broken" },{ id: 9, type: { name: "C" }, condition: "broken" }]; const map = new Map(data.map(o => [o.type.name, { by: { type: o.type.name }, chunks: [] }])); data.forEach(o => map.get(o.type.name).chunks.push(o)); const result = [...map.values()]; console.log(result); 

Here you go: 干得好:

 const data = [ { id: 1, type: { name: "A" }, condition: "new" }, { id: 2, type: { name: "C" }, condition: "broken" }, { id: 3, type: { name: "C" }, condition: "brand new" }, { id: 4, type: { name: "B" }, condition: "broken" }, { id: 5, type: { name: "C" }, condition: "brand new" }, { id: 6, type: { name: "A" }, condition: "new" }, { id: 7, type: { name: "A" }, condition: "new" }, { id: 8, type: { name: "B" }, condition: "broken" }, { id: 9, type: { name: "C" }, condition: "broken" } ]; let names = []; data.forEach(x => { if (names.indexOf(x.type.name)==-1) { names.push(x.type.name); } }); let grouped = names.map(name => ({ by: { type: {name}}, chunks: data.filter(x => x.type.name==name) })); console.log(grouped); 

Since you can't group by an object because two objects with the same keys and values are not the same object, you can use JSON.stringify() to convert the object to a string, and group by it. 由于无法对对象进行分组,因为两个具有相同键和值的对象不是同一对象,因此可以使用JSON.stringify()将对象转换为字符串,然后对其进行分组。 Use Array.reduce() to group the items by the stringified object. 使用Array.reduce()按字符串对象对项目进行分组。 Convert to pairs using Object.entries() , then map the values to an object, and extract the by value using JSON.parse() : 使用Object.entries()转换为对,然后将值映射到对象,并使用JSON.parse()提取by值:

 const groupByObj = (arr, key) => Object.entries( arr.reduce((r, o) => { const k = JSON.stringify({ [key]: o[key] }); r[k] = r[k] || []; r[k].push(o); return r; }, {}) ).map(([k, chunks]) => ({ by: JSON.parse(k), chunks })); const data = [{"id":1,"type":{"name":"A"},"condition":"new"},{"id":2,"type":{"name":"C"},"condition":"broken"},{"id":3,"type":{"name":"C"},"condition":"brand new"},{"id":4,"type":{"name":"B"},"condition":"broken"},{"id":5,"type":{"name":"C"},"condition":"brand new"},{"id":6,"type":{"name":"A"},"condition":"new"},{"id":7,"type":{"name":"A"},"condition":"new"},{"id":8,"type":{"name":"B"},"condition":"broken"},{"id":9,"type":{"name":"C"},"condition":"broken"}]; const result = groupByObj(data, 'type'); console.log(result); 

You could use reduce and Object.values to group like this: 您可以使用reduceObject.values进行分组,如下所示:

 const data = [{"id":1,"type":{"name":"A"},"condition":"new"},{"id":2,"type":{"name":"C"},"condition":"broken"},{"id":3,"type":{"name":"C"},"condition":"brand new"},{"id":4,"type":{"name":"B"},"condition":"broken"},{"id":5,"type":{"name":"C"},"condition":"brand new"},{"id":6,"type":{"name":"A"},"condition":"new"},{"id":7,"type":{"name":"A"},"condition":"new"},{"id":8,"type":{"name":"B"},"condition":"broken"},{"id":9,"type":{"name":"C"},"condition":"broken"}]; const merged = data.reduce((acc, o) => { const {type} = o; acc[type.name] = acc[type.name] || { by: { type }, chunks:[] }; acc[type.name].chunks.push(o) return acc; },{}) const output = Object.values(merged) console.log(output) 

(Ignore snippet console and check browser's console) (忽略代码段console并检查浏览器的控制台)

You can use reduce 您可以使用减少

Here the idea is 这里的想法是

  • Use name as key and checks if op already has that particular key or not. 使用name作为键,并检查op已经具有该特定键。 if the key is already there we push the inp to chunks property of op. 如果键已经存在,我们将op的inpchunks属性。 if not we add a new key with by and chunks with respective values. 如果不是,我们用bychunks分别添加一个新的键。

 const data = [{ id: 1, type: { name: "A" }, condition: "new" },{ id: 2, type: { name: "C" }, condition: "broken" },{ id: 3, type: { name: "C" }, condition: "brand new" },{ id: 4, type: { name: "B" }, condition: "broken" },{ id: 5, type: { name: "C" }, condition: "brand new" },{ id: 6, type: { name: "A" }, condition: "new" },{ id: 7, type: { name: "A" }, condition: "new" },{ id: 8, type: { name: "B" }, condition: "broken" },{ id: 9, type: { name: "C" }, condition: "broken" }]; let op = data.reduce( (op,inp) => { if( op[inp.type] ){ op[inp].chunks.push(inp) } else { op[inp] = { by: {...inp.type}, chunks: [inp] } } return op },{}) console.log(Object.values(op)) 

Using lodash as you mentioned before we could do: 使用您之前提到的lodash可以做到:

 const data = [ { id: 1, type: { name: "A" }, condition: "new" }, { id: 2, type: { name: "C" }, condition: "broken" }, { id: 3, type: { name: "C" }, condition: "brand new" }, { id: 4, type: { name: "B" }, condition: "broken" }, { id: 5, type: { name: "C" }, condition: "brand new" }, { id: 6, type: { name: "A" }, condition: "new" }, { id: 7, type: { name: "A" }, condition: "new" }, { id: 8, type: { name: "B" }, condition: "broken" }, { id: 9, type: { name: "C" }, condition: "broken" } ]; const groups = _.groupBy(data, (val) => val.type.name) const formattedGroupd = Object.keys(groups).map(groupKey => { return { by: {type: { name: groupKey }}, chunks: groups[groupKey] } }); console.log(formattedGroupd) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script> 

You just need to change the way you assing the value to by in map. 您只需要更改在地图中by值的方式即可。 Assign like 分配像

 return {
      chunks: item,
      by: { type: item[0].type} 
    };

 const data = [ { id: 1, type: { name: "A" }, condition: "new" }, { id: 2, type: { name: "C" }, condition: "broken" }, { id: 3, type: { name: "C" }, condition: "brand new" }, { id: 4, type: { name: "B" }, condition: "broken" }, { id: 5, type: { name: "C" }, condition: "brand new" }, { id: 6, type: { name: "A" }, condition: "new" }, { id: 7, type: { name: "A" }, condition: "new" }, { id: 8, type: { name: "B" }, condition: "broken" }, { id: 9, type: { name: "C" }, condition: "broken" } ]; console.log(_.chain(data) .groupBy("type.name") .map((item, i) => { return { by: { type: item[0].type}, chunks: item }; }) .value()) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script> 

const data = [
    { id: 1, type: { name: "A" }, condition: "new" },
    { id: 2, type: { name: "C" }, condition: "broken" },
    { id: 3, type: { name: "C" }, condition: "brand new" },
    { id: 4, type: { name: "B" }, condition: "broken" },
    { id: 5, type: { name: "C" }, condition: "brand new" },
    { id: 6, type: { name: "A" }, condition: "new" },
    { id: 7, type: { name: "A" }, condition: "new" },
    { id: 8, type: { name: "B" }, condition: "broken" },
    { id: 9, type: { name: "C" }, condition: "broken" }
];

const data2 = {};

data.forEach(test => {

    if (data2[test.type.name]) {
        data2[test.type.name].chunks.push({
            test
        });
    } else {
        data2[test.type.name] = {
            by: {
                type: test.type
            },
            chunks: [
                test
            ]
        };
    }
});

console.log(Object.values(data2));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM