代码之家  ›  专栏  ›  技术社区  ›  Emad Dehnavi

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

  •  3
  • Emad Dehnavi  · 技术社区  · 6 年前

    这是对象的输入数组:

    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 ,因此所有具有相同值的对象 姓名、家庭、号码和类别 应该有一个单独的数组。

    我尝试了很多东西,我用了两个嵌套的for循环,我用了map,我用了filter,…我尽了我所能,但我做不到!

    如果有人能帮上忙,我真的很感激。

    3 回复  |  直到 6 年前
        1
  •  1
  •   Nina Scholz    6 年前

    你可以拿一个 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; }

    对于多个组,可以使用一个联接键,该键的值为 name , family , number 类别 在一个封闭的 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);
    .作为控制台包装最大高度:100%!重要;顶部:0;
        2
  •  2
  •   amrender singh    6 年前

    只需使用 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);
        3
  •  1
  •   Ankit Agarwal    6 年前

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