Как сгруппировать данные? - PullRequest
0 голосов
/ 27 апреля 2018

Как написать скрипт, который группирует элементы массива в массив массивов (или объект массивов), где последний - это массив элементов, сгруппированных по последовательности.

Если следующий элемент Id является частью последовательности, он попадает в предыдущую группу, в противном случае будет создан новый массив и элемент попадет в него.

Если Id элемента больше, чем Id элемента prev, больше чем 1 - это та же последовательность = текущий массив.

Если Id элемента больше, чем Id элемента ранее, чем 2, - это следующая последовательность = следующий (новый) массив.

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

Неважно, будет ли это массив или объект - генерировать ключи легко, но групповые элементы для меня сейчас трудны.

Вы можете попробовать писать на JavaScript, вы даже можете использовать библиотеку Lodash.

const data = [
{id: 1},
{id: 2},
{id: 3},
{id: 7},
{id: 9},
{id: 10},
{id: 12},
{id: 14},
{id: 15},
{id: 16}];

==========================================

const result = [
0/"1-4": [
    {id: 1},
    {id: 2},
    {id: 3},
    {id: 4}],
1/"7": [
    {id: 7}],
2/"9-10": [
    {id: 9},
    {id: 10}],
3/"12": [
    {id: 12}],
4/"14-16": [
    {id: 14},
    {id: 15},
    {id: 16}]];

Ответы [ 3 ]

0 голосов
/ 27 апреля 2018

Вы можете использовать цепочечные Array.reduce() вызовы для создания необходимой структуры:

const data = [{"id":1},{"id":2},{"id":3},{"id":7},{"id":9},{"id":10},{"id":12},{"id":14},{"id":15},{"id":16}];

const arrayOfGroups = data
  .reduce((r, o, i) => {
    // if first or not sequence add new sub array
    if(!r.length || o.id !== data[i - 1].id + 1) r.push([]);
    
    // push to last sub array
    r[r.length - 1].push(o);
    
    return r;
  }, []);
  
const objectOfGroups = arrayOfGroups.reduce((r, a, i) => {
    const start = a[0].id;
    const end = a[a.length - 1].id;
    // if start and end are equal, add just start (to main the order of insertion, start can be just a number)
    const key = start === end ? 
      `${i}/${start}` : `${i}/${start}-${end}`;
    
    r[key] = a;
  
    return r;
  }, {});
  
console.log('arrayOfGroups', arrayOfGroups);

console.log('objectOfGroups', objectOfGroups);
0 голосов
/ 27 апреля 2018

Вы можете использовать однопетлевой подход, проверив последний массив набора результатов и проверив последний объект id, если он находится в требуемом диапазоне.

Если нет, то добавьте новый пустой массив в набор результатов. Позже перенесите фактический объект в последний массив.

var data = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 7 }, { id: 9 }, { id: 10 }, { id: 12 }, { id: 14 }, { id: 15 }, { id: 16 }],
    grouped = data.reduce((r, o) => {
        var last = r[r.length - 1];
        if (!last || last[last.length - 1].id + 1 !== o.id) {
            r.push(last = []);
        }
        last.push(o);
        return r;
    }, []);

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 27 апреля 2018

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

const data = [
  {id: 1},
  {id: 2},
  {id: 3},
  {id: 7},
  {id: 9},
  {id: 10},
  {id: 12},
  {id: 14},
  {id: 15},
  {id: 16}]
.sort((a,b)=>a.id-b.id)//make sure it is sorted by id
.reduce(
  ([result,nextNum],item)=>{//nextNum is the next expected number
    if(nextNum===undefined){//first time nextNum is undefined
      nextNum=item.id;//set nextNum to id of current item
      result.push([]);//add empty array
    }
    if(!(nextNum===item.id)){//current item id is not the expected next number
      result.push([]);//add empty array
    }
    result[result.length-1].push(item);//add item to last array of the array of arrays
    return [result,item.id+1];//next expected number is current item id + 1
  },
  [[],undefined]//initial values for result and nextNum
);
console.log(data)
...