Javascript группа и массив рекурсивно по нескольким свойствам в определенном порядке - PullRequest
0 голосов
/ 24 октября 2018

Я создаю компонент сетки, который позволит пользователю группировать несколько строк.

Исходные данные, над которыми я работаю, являются примером для стандартных товаров:

let stock = [
    { order: "200", type: "production", qty: 200, item: "IT282" },
    { order: "200", type: "production", qty: 90, item: "IT283" },
    { order: "200", type: "customer", qty: 80, item: "IT102" },
    { order: "200", type: "production", qty: 110, item: "IT283" },
    { order: "200", type: "customer", qty: 130, item: "IT102" },
    { order: "200", type: "production", qty: 45, item: "IT233" },
    { order: "200", type: "stock", qty: 30, item: "IT282" },
    { order: "210", type: "production", qty: 300, item: "IT282" },
    { order: "210", type: "production", qty: 190, item: "IT283" },
    { order: "210", type: "customer", qty: 180, item: "IT102" },
    { order: "210", type: "production", qty: 210, item: "IT283" },
    { order: "210", type: "customer", qty: 230, item: "IT102" },
    { order: "210", type: "production", qty: 145, item: "IT233" },
    { order: "210", type: "stock", qty: 130, item: "IT282" }
];

Что мне нужно сделать, так это уметь группировать эти данные, используя несколько полей в разных порядках, например, следующие результаты:

let result = groupBy(stock, ["order"]);

[
    {
        field: "order",
        value: "200",
        rows: [
            { order: "200", type: "production", qty: 200, item: "IT282" },
            { order: "200", type: "production", qty: 90, item: "IT283" },
            { order: "200", type: "customer", qty: 80, item: "IT102" },
            { order: "200", type: "production", qty: 110, item: "IT283" },
            { order: "200", type: "customer", qty: 130, item: "IT102" },
            { order: "200", type: "production", qty: 45, item: "IT233" },
            { order: "200", type: "stock", qty: 30, item: "IT282" }
        ]
    },
    {
        field: "order",
        value: "210",
        rows: [
            { order: "210", type: "production", qty: 300, item: "IT282" },
            { order: "210", type: "production", qty: 190, item: "IT283" },
            { order: "210", type: "customer", qty: 180, item: "IT102" },
            { order: "210", type: "production", qty: 210, item: "IT283" },
            { order: "210", type: "customer", qty: 230, item: "IT102" },
            { order: "210", type: "production", qty: 145, item: "IT233" },
            { order: "210", type: "stock", qty: 130, item: "IT282" }
        ]
    }
];

let result = groupBy(stock, ["item"]);

[
    {
        field: "item",
        value: "IT282",
        rows: [
            { order: "200", type: "production", qty: 200, item: "IT282" },
            { order: "200", type: "stock", qty: 30, item: "IT282" },
            { order: "210", type: "production", qty: 300, item: "IT282" },
            { order: "210", type: "stock", qty: 130, item: "IT282" }
        ]
    },
    {
        field: "item",
        value: "IT283",
        rows: [
            { order: "200", type: "production", qty: 90, item: "IT283" },
            { order: "200", type: "production", qty: 110, item: "IT283" },
            { order: "210", type: "production", qty: 190, item: "IT283" },
            { order: "210", type: "production", qty: 210, item: "IT283" }
        ]
    },
    {
        field: "item",
        value: "IT102",
        rows: [
            { order: "200", type: "customer", qty: 80, item: "IT102" },
            { order: "200", type: "customer", qty: 130, item: "IT102" },
            { order: "210", type: "customer", qty: 180, item: "IT102" },
            { order: "210", type: "customer", qty: 230, item: "IT102" }
        ]
    },
    {
        field: "item",
        value: "IT233",
        rows: [
            { order: "200", type: "production", qty: 45, item: "IT233" },
            { order: "210", type: "production", qty: 145, item: "IT233" }
        ]
    }
];

let result = groupBy(stock, ["order", "item"]);

[
    {
        field: "order",
        value: "200",
        rows: [
            {
                field: "item",
                value: "IT282",
                rows: [
                    {
                        order: "200",
                        type: "production",
                        qty: 200,
                        item: "IT282"
                    },
                    { order: "200", type: "stock", qty: 30, item: "IT282" },
                    {
                        order: "210",
                        type: "production",
                        qty: 300,
                        item: "IT282"
                    }
                ]
            },
            {
                field: "item",
                value: "IT283",
                rows: [
                    {
                        order: "200",
                        type: "production",
                        qty: 90,
                        item: "IT283"
                    },
                    {
                        order: "200",
                        type: "production",
                        qty: 110,
                        item: "IT283"
                    }
                ]
            },
            {
                field: "item",
                value: "IT102",
                rows: [
                    { order: "200", type: "customer", qty: 80, item: "IT102" },
                    { order: "200", type: "customer", qty: 130, item: "IT102" }
                ]
            },
            {
                field: "item",
                value: "IT233",
                rows: [
                    {
                        order: "200",
                        type: "production",
                        qty: 45,
                        item: "IT233"
                    }
                ]
            }
        ]
    },
    {
        field: "order",
        value: "210",
        rows: [
            {
                field: "item",
                value: "IT282",
                rows: [{ order: "210", type: "stock", qty: 130, item: "IT282" }]
            },
            {
                field: "item",
                value: "IT283",
                rows: [
                    {
                        order: "210",
                        type: "production",
                        qty: 190,
                        item: "IT283"
                    },
                    {
                        order: "210",
                        type: "production",
                        qty: 210,
                        item: "IT283"
                    }
                ]
            },
            {
                field: "item",
                value: "IT102",
                rows: [
                    { order: "210", type: "customer", qty: 180, item: "IT102" },
                    { order: "210", type: "customer", qty: 230, item: "IT102" }
                ]
            },
            {
                field: "item",
                value: "IT233",
                rows: [
                    {
                        order: "210",
                        type: "production",
                        qty: 145,
                        item: "IT233"
                    }
                ]
            }
        ]
    }
];

let result = groupBy(stock, ["item", "order"]);

[
    {
        field: "item",
        value: "IT282",
        rows: [
            {
                field: "order",
                value: "200",
                rows: [
                    {
                        order: "200",
                        type: "production",
                        qty: 200,
                        item: "IT282"
                    },
                    { order: "200", type: "stock", qty: 30, item: "IT282" }
                ]
            },
            {
                field: "order",
                value: "210",
                rows: [
                    {
                        order: "210",
                        type: "production",
                        qty: 300,
                        item: "IT282"
                    },
                    { order: "210", type: "stock", qty: 130, item: "IT282" }
                ]
            }
        ]
    },
    {
        field: "item",
        value: "IT283",
        rows: [
            {
                field: "order",
                value: "200",
                rows: [
                    {
                        order: "200",
                        type: "production",
                        qty: 90,
                        item: "IT283"
                    },
                    {
                        order: "200",
                        type: "production",
                        qty: 110,
                        item: "IT283"
                    }
                ]
            },
            {
                field: "order",
                value: "210",
                rows: [
                    {
                        order: "210",
                        type: "production",
                        qty: 190,
                        item: "IT283"
                    },
                    {
                        order: "210",
                        type: "production",
                        qty: 210,
                        item: "IT283"
                    }
                ]
            }
        ]
    },
    {
        field: "item",
        value: "IT102",
        rows: [
            {
                field: "order",
                value: "200",
                rows: [
                    { order: "200", type: "customer", qty: 80, item: "IT102" },
                    { order: "200", type: "customer", qty: 130, item: "IT102" }
                ]
            },
            {
                field: "order",
                value: "210",
                rows: [
                    { order: "210", type: "customer", qty: 180, item: "IT102" },
                    { order: "210", type: "customer", qty: 230, item: "IT102" }
                ]
            }
        ]
    },
    {
        field: "item",
        value: "IT233",
        rows: [
            {
                field: "order",
                value: "200",
                rows: [
                    { order: "200", type: "production", qty: 45, item: "IT233" }
                ]
            },
            {
                field: "order",
                value: "210",
                rows: [
                    {
                        order: "210",
                        type: "production",
                        qty: 145,
                        item: "IT233"
                    }
                ]
            }
        ]
    }
];

Моя групповая функция получит любой массив элементов и сгруппирует любое количествополя массива в любом порядке.

Поскольку я хочу функцию на основе ES6, я сегодня использую следующую groupBy функцию из , которая связывает , которая работает для одного прохода, но у меня возникают трудности с вложением потом вместе.

Вот код, над которым я работаю:

  groupBy = (rows, groups) => {
    if (groups.length === 0) return rows;

    return this.groupByField(rows, groups, 0);
  };

  groupByField = (rows, groups, index) => {
    if (index >= groups.length) return rows;

    let grouped = this.groupRows(rows, groups[index]);

    index++;
    let ret = [];

    grouped.rows.map(row => {
      ret.push(this.groupByField(row.rows, groups, index));
    });

    grouped.rows = ret;
    return grouped;
  };

  groupRows = (rows, field) => {
    return rows.reduce(function(groups, x) {
      let val = helper.getValueByFieldNameString(x.data, field);

      let found = groups.find(item => {
        return item.groupedValue === val;
      });

      if (!found) {
        let rows = [];
        rows.push(x);

        groups.push({
          groupedField: field,
          groupedValue: val,
          rows: rows
        });
      } else {
        found.rows.push(x);
      }

      return groups;
    }, []);
  };

Кажется, что рекурсивность не работает должным образом.

1 Ответ

0 голосов
/ 24 октября 2018

Я думаю, вы можете просто создать функцию, которая группирует массив, используя reduce и Object.values.Затем, после группировки массива, если у вас есть больше полей для группировки, вызовите функцию для каждого дочернего row массива.Например:

let stock = [{ order: "200", type: "production", qty: 200, item: "IT282" },{ order: "200", type: "production", qty: 90, item: "IT283" },{ order: "200", type: "customer", qty: 80, item: "IT102" },{ order: "200", type: "production", qty: 110, item: "IT283" },{ order: "200", type: "customer", qty: 130, item: "IT102" },{ order: "200", type: "production", qty: 45, item: "IT233" },{ order: "200", type: "stock", qty: 30, item: "IT282" },{ order: "210", type: "production", qty: 300, item: "IT282" },{ order: "210", type: "production", qty: 190, item: "IT283" },{ order: "210", type: "customer", qty: 180, item: "IT102" },{ order: "210", type: "production", qty: 210, item: "IT283" },{ order: "210", type: "customer", qty: 230, item: "IT102" },{ order: "210", type: "production", qty: 145, item: "IT233" },{ order: "210", type: "stock", qty: 130, item: "IT282" }];

function groupBy(arr, fields) {
  let field = fields[0]               // one field at a time
  if (!field) return arr              
  let retArr = Object.values(
     arr.reduce((obj, current) => {
        if (!obj[current[field]]) obj[current[field]] = {field: field, value: current[field],rows: []}
        obj[current[field]].rows.push(current)
        return obj
     }, {}))
  
  // recurse for each child's rows if there are remaining fields
  if (fields.length){
      retArr.forEach(obj => {
          obj.count = obj.rows.length
          obj.rows = groupBy(obj.rows, fields.slice(1))
      })
  }
  return retArr
}

let result = groupBy(stock, ["order", "item"]);
console.log(result)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...