Как сгруппировать массивы в массив по ключу объекта первого элемента - PullRequest
1 голос
/ 30 мая 2019

Получил массив массивов, подобный этому:

    let arr = [
      [
        {"key":2, "other":123},
        {"key":2, "other":222}
      ],
      [
        {"key":3, "other":0}
      ],
      [
        {"key":1, "other":11},
        {"key":1, "other":23}
      ],
      [
        {"key":1, "other":22}
      ]
    ]

Мне нужно получить это arr, но с сгруппированными массивами с таким же значением "ключа" первого элемента, так что это будет выглядеть так:

  let arr = [
      [
        {"key":2, "other":123},
        {"key":2, "other":222}
      ],
      [
        {"key":3, "other":0}
      ],
      [
        [
          {"key":1, "other":11},
          {"key":1, "other":23}
        ],
        [
          {"key":1, "other":22}
        ]
      ],

    ]

Я пытался использовать функцию уменьшения, но результат был совершенно другим.

let final = []
  for (let i=0; i<arr.length; i++) {

    let arr1 = i==0?arr:arr.slice(i)

    let final1 = arr1.reduce((acc,x)=> {

      acc = acc[0].key==x[0].key?acc.concat(x):acc
      return acc
    })
    arr1.length>1&&final.push(final1)
  }

В этом коде проблема заключается в том, что он сравнивает arr [1] с arr [2], arr [3], а затем снова arr [2] с arr [3] и группирует его (хотяarr [1] .key и arr [2] .key и arr [3] .key одинаковы) Можете ли вы дать несколько советов или дать заключительную функцию для этого?

Ответы [ 4 ]

1 голос
/ 30 мая 2019
let arr = [
      [
        {"key":2},
        {"key":2}
      ],
      [
        {"key":3}
      ],
      [
        {"key":1},
        {"key":1}
      ],
      [
        {"key":1}
      ]
    ]
var myMap = new Map();
for (i = 0; i < arr.length; i++) { 
    if(!myMap.has(arr[i][0]['key'])){
        myMap.set(arr[i][0]['key'],i)
    }else if(myMap.get(arr[i][0]['key'])===undefined){

        myMap.set(arr[i][0]['key'],i)
    }else{
        myMap.set(arr[i][0]['key'],myMap.get(arr[i][0]['key'])+','+i)
    }
}
var out =[];
for(var v of myMap.values()){
    var s = String(v).split(",");
    var fi = s[0]
    var subarray =[]
    for(var i in s){
        subarray.push(arr[s[i]]) 
    }
    out[fi] = subarray;
}

Вы найдете ответ в массиве.Надеюсь, что это работает для вас

1 голос
/ 30 мая 2019

Создайте объект keys вместе с его количеством. Затем вы можете отфильтровать ключи, которые присутствуют более одного раза, i: e (count >= 2). Затем выполните итерацию по входному массиву, используя reduce, и посмотрите, присутствует ли он в ключах отфильтрованного массива; если да, вставьте отдельный массив, а другое - accu. Затем объедините два массива в один.

let input = [
    [
      {"key":2, "other":123},
      {"key":2, "other":222}
    ],
    [
      {"key":3, "other":0}
    ],
    [
      {"key":1, "other":11},
      {"key":1, "other":23}
    ],
    [
      {"key":1, "other":22}
    ]
];

// keys with unique key and its count. filter whose count are greater than two.

const groupByArrKeysOccurence = input.reduce((accu, arr) => {
    const key = arr[0].key;
    accu[key] = (accu[key] || 0) + 1;
    return accu;
}, {});

const filteredKeys = Object.entries(groupByArrKeysOccurence).filter(([_, val]) => val > 1).map(([key, _]) => Number(key));

const multipleArrOccurenceKeys = [];

const singleArrOccurenceKeys = input.reduce((accu, arr) => {
    const isKey = arr.some(({key}) => filteredKeys.includes(key));
    if(isKey) {
        multipleArrOccurenceKeys.push(arr);
    } else {
        accu.push(arr);
    }
    return accu;
}, []);

console.log([...singleArrOccurenceKeys, multipleArrOccurenceKeys]);
0 голосов
/ 30 мая 2019

Это решение не дает точного результата, который вы ищете, но оно красивое и чистое.Результат, который вы хотите получить, скорее всего, доставит вам неприятности в будущем, поскольку некоторые элементы вложены дальше, чем другие.

В этом ответе предполагается, что в каждом массиве всегда есть хотя бы один элемент, поскольку вопрос заключается всгруппировать по ключу первого элемента.

let arr = [[{"key":2, "other":123}, {"key":2, "other":222}], [{"key":3, "other":0}], [{"key":1, "other":11}, {"key":1, "other":23}], [{"key":1, "other":22}]];

let groups = {};
let group = key => groups[key] || (groups[key] = []);
arr.forEach(arr => group(arr[0].key).push(arr));

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

// If you want to get the result you're looking for (not looking at the
// order), you can simply flatten all groups of 1 element. Although
// depending on your use case I recommend sticking with the above.

console.log(Object.values(groups).map(group => group.length === 1 ? group[0] : group));
0 голосов
/ 30 мая 2019

Я думаю, что вы хотите что-то вроде этого, попробуйте запустить фрагмент

let arr = [
    [
        {
            "key": 2
        },
        {
            "key": 2
        }
    ],
    [
        {
            "key": 3
        }
    ],
    [
        {
            "key": 1
        },
        {
            "key": 1
        }
    ],
    [
        {
            "key": 1
        }
    ]
]


let result = arr.reduce((res, array) => {
    array.forEach((value, index) => {
        const obj = res.find(a => {
            return !!a.find(({key}) => {
                return key === value.key
            })
        })
        if (obj) {
            obj.push(value)
        } else {
            res.push([value])
        }
    })
    return res;
}, [])


console.log(result);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...