根据对象数组中的重复值将对象分组

时间:2018-07-21 08:18:15

标签: javascript arrays node.js loops object

这是对象的输入数组:

var array = [{
    id: 1,
    name: 'A',
    family: 'B',
    number: 100,
    category: 'test',
    time: '2018-03-02T10:33:00.000Z'
  },
  {
    id: 2,
    name: 'A',
    family: 'B',
    number: 100,
    category: 'test',
    time: '2018-03-02T10:33:50.000Z'
  },
  {
    id: 3,
    name: 'A',
    family: 'B',
    number: 100,
    category: 'test',
    time: '2018-03-02T10:34:30.000Z'
  },
  {
    id: 4,
    name: 'A',
    family: 'B',
    number: 100,
    category: 'test',
    time: '2018-03-02T10:36:00.000Z'
  },
  {
    id: 5,
    name: 'A',
    family: 'C',
    number: 250,
    category: 'other',
    time: '2018-03-02T10:33:00.000Z'
  },
  {
    id: 6,
    name: 'A',
    family: 'C',
    number: 250,
    category: 'other',
    time: '2018-03-02T10:33:05.000Z'
  }
]

我想像这样将其分组为输出:

var output = [
  [{
      id: 1,
      name: 'A',
      family: 'B',
      number: 100,
      category: 'test',
      time: '2018-03-02T10:33:00.000Z'
    },
    {
      id: 2,
      name: 'A',
      family: 'B',
      number: 100,
      category: 'test',
      time: '2018-03-02T10:33:50.000Z'
    },
    {
      id: 3,
      name: 'A',
      family: 'B',
      number: 100,
      category: 'test',
      time: '2018-03-02T10:34:30.000Z'
    },
    {
      id: 4,
      name: 'A',
      family: 'B',
      number: 100,
      category: 'test',
      time: '2018-03-02T10:36:00.000Z'
    }
  ],
  [{
      id: 5,
      name: 'A',
      family: 'C',
      number: 250,
      category: 'other',
      time: '2018-03-02T10:33:00.000Z'
    },
    {
      id: 6,
      name: 'A',
      family: 'C',
      number: 250,
      category: 'other',
      time: '2018-03-02T10:33:05.000Z'
    }
  ]
]

如您所见,只有id and time是唯一的,我想根据重复项name, family, number and category对其进行分组,因此,name, family, number and category具有相同值的所有对象都应具有一个单独的数组。

我尝试了很多事情,我使用了两个嵌套的for循环,我使用了map,我对Filter进行了起诉,...我尝试了所有我能想到的,但是我却做不到!

如果有人可以帮助您,我真的很感激。

3 个答案:

答案 0 :(得分:2)

只需使用Array.reduce()和组合键name, family,number and category制作地图。然后您可以在该地图上使用Object.values()来获得所需的结果。

var array =[ { id: 1, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:33:00.000Z' }, { id: 2, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:33:50.000Z' }, { id: 3, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:34:30.000Z' }, { id: 4, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:36:00.000Z' }, { id: 5, name: 'A', family: 'C', number: 250, category: 'other', time: '2018-03-02T10:33:00.000Z' }, { id: 6, name: 'A', family: 'C', number: 250, category: 'other', time: '2018-03-02T10:33:05.000Z' } ];

var result = Object.values(array.reduce((a,curr)=>{
  var key = curr.name + "_" + curr.family + "_" + curr.number + "_" + curr.category;
  (a[key] = a[key] || []).push(curr);
  return a;
},{}));

console.log(result);

答案 1 :(得分:1)

您可以使用Map并将同一组中的所有项目收集到一个阵列中。

以后仅获取地图的值作为结果。

这仅适用于一组category

var array = [{ id: 1, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:33:00.000Z' }, { id: 2, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:33:50.000Z' }, { id: 3, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:34:30.000Z' }, { id: 4, name: 'A', family: 'B', number: 100, category: 'test', time: '2018-03-02T10:36:00.000Z' }, { id: 5, name: 'A', family: 'C', number: 250, category: 'other', time: '2018-03-02T10:33:00.000Z' }, { id: 6, name: 'A', family: 'C', number: 250, category: 'other', time: '2018-03-02T10:33:05.000Z' }],
    grouped = Array.from(array.reduce((m, o) =>
        m.set(o.category, (m.get(o.category) || []).concat(o)), new Map).values());

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

对于多个组,您可以在一个闭包中使用一个连接键,其中包含namefamilynumbercategory的实际对象的值key

然后映射具有关闭时间的新数组,并将所有数组组合为单个嵌套数组。在末尾按长度过滤。

var array = [{ id: 1, sourceAccount: "A", targetAccount: "B", amount: 100, category: "eating_out", time: "2018-03-02T10:33:00.000Z" }, { id: 2, sourceAccount: "A", targetAccount: "B", amount: 100, category: "eating_out", time: "2018-03-02T10:33:50.000Z" }, { id: 3, sourceAccount: "A", targetAccount: "B", amount: 100, category: "eating_out", time: "2018-03-02T10:34:30.000Z" }, { id: 4, sourceAccount: "A", targetAccount: "B", amount: 100, category: "eating_out", time: "2018-03-02T10:36:00.000Z" }, { id: 5, sourceAccount: "A", targetAccount: "C", amount: 250, category: "other", time: "2018-03-02T10:33:00.000Z" }, { id: 6, sourceAccount: "A", targetAccount: "C", amount: 250, category: "other", time: "2018-03-02T10:33:05.000Z" }],
    groupBy = ['name', 'family', 'number', 'category'],
    result = Array
        .from(
            array
                .reduce((m, o) => (k => m.set(k, (m.get(k) || []).concat(o)))(groupBy.map(k => o[k]).join('|')), new Map)
                .values(),
            o => o.sort((a, b) => a.time.localeCompare(b.time))
        )
        .map(g => g.reduce((r, o, i, a) => {
            if (!i || new Date(o.time).getTime() - new Date(a[i - 1].time).getTime() > 60000) {
                r.push([o]);
            } else {
                r[r.length - 1].push(o);
            }
            return r;
        }, []))
        .reduce((r, a) => r.concat(a), [])
        .filter(a => a.length > 1);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:1)

您还可以使用Array.reduce()获得该输出:

var array = [ { id: 1,
  name: 'A',
  family: 'B',
  number: 100,
  category: 'test',
  time: '2018-03-02T10:33:00.000Z' },
  { id: 2,
  name: 'A',
  family: 'B',
  number: 100,
  category: 'test',
  time: '2018-03-02T10:33:50.000Z' },
  { id: 3,
  name: 'A',
  family: 'B',
  number: 100,
  category: 'test',
  time: '2018-03-02T10:34:30.000Z' },
  { id: 4,
  name: 'A',
  family: 'B',
  number: 100,
  category: 'test',
  time: '2018-03-02T10:36:00.000Z' },
  { id: 5,
  name: 'A',
  family: 'C',
  number: 250,
  category: 'other',
  time: '2018-03-02T10:33:00.000Z' },
  { id: 6,
  name: 'A',
  family: 'C',
  number: 250,
  category: 'other',
  time: '2018-03-02T10:33:05.000Z' } 

];

var res = array.reduce((acc, obj)=>{
  var existObj;
  for(var i = 0 ; i < acc.length; i++) {
    let accArray = acc[i];
    if(accArray){
     existObj = accArray.find(({name, family, number, category}) =>  name == obj.name && family == obj.family && number == obj.number && category == obj.category);
     if(existObj) {
        accArray.push(obj);
        return acc;
     }
    }
 }
  acc.push([obj]);
  return acc;
}, []);
console.log(res);