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

时间:2019-02-22 19:50:15

标签: javascript arrays sorting

我有一个这样的对象数组:

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" }
    ];

我要做的是按类型将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" }
        ]
      },
    ];

我尝试使用lodash和Array.prototype.reduce(),最后一次尝试使用lodash,但我无法将类型作为对象。

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

8 个答案:

答案 0 :(得分:1)

您可以使用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);

答案 1 :(得分:1)

您在这里:

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);

答案 2 :(得分:1)

由于不能将对象分组,因为两个具有相同键和值的对象不是同一对象,因此可以使用JSON.stringify()将对象转换为字符串并进行分组。使用Array.reduce()按字符串对象对项目进行分组。使用Object.entries()转换为对,然后将值映射到对象,并使用by提取JSON.parse()值:

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);

答案 3 :(得分:1)

您可以使用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)

(忽略代码段console,并检查浏览器的控制台)

答案 4 :(得分:0)

您可以使用reduce

这里的想法是

  • 使用name作为密钥,并检查op是否已经具有该特定密钥。如果键已经存在,我们将op的inp推到chunks属性。如果没有,我们用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))

答案 5 :(得分:0)

使用您之前提到的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>

答案 6 :(得分:0)

您只需要更改将值关联到地图中的by的方式。像分配

 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>

答案 7 :(得分:0)

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));