从数组中分组数据

时间:2017-03-05 15:42:03

标签: javascript arrays

我有一个包含不同对象的数组,其中每个对象都是一个订单。 看起来像这样:

array = [
    {
    doc : {
      date: "2017-03-06T16:48:23.080Z",
      products:[
        {
          product: "Product 1",
          number: 3
        },
        {
          product: "Product 2",
          number: 2
        }
      ]
    }
  },
  {
    doc : {
      date: "2017-03-07T16:48:23.080Z",
      products:[
        {
          product: "Product 2",
          number: 10
        },
        {
          product: "Product 3",
          number: 1
        }
      ]
    }
  }
]

我希望能够获取这些数据并将其推送到新数组中,其中每个数据都有一个日期属性(按日期分组),以及一个产品嵌套数组,它对不同的订单进行分组(按产品分组)。像这样:

array = [
    {
       date: 'Date X',
       products: [
         {
          product: 'product 1',
          units: 3
         },
         {
          product: 'product 2',
          units: 2
         }
      ]    
    },
    {
       date: 'Date Y',
       products: [
         {
          product: 'product 2',
          units: 10
         },
         {
          product: 'product 3',
          units: 1
         }

      ]
    }
]

你会怎么做?我已经尝试过Lodash试图重用一些旧代码,但到目前为止没有运气。可以用forEach吗?

3 个答案:

答案 0 :(得分:1)

使用lodash和ES6的解决方案:

// Remove unnecesary .doc properties
let arrayWithoutDoc = _.map(array, el => el.doc);

// Group by dates to single object
let grouped = _.groupBy(arrayWithoutDoc, el => el.date);

// Convert object to requested format
let result = _.map(grouped, (value, date) => ({
    date: date,
    products: sumProductsUnits(
        _.flatMap(value, el => el.products)
    )
}));

// Function for grouping unique products with sum of units
function sumProductsUnits(products) {
    var productGroups = _.groupBy(products, productObj => productObj.product);

    return _.map(productGroups, (productGroup, productName) => ({
        product: productName,
        units: productGroup.reduce((sum, val) => sum + val.number, 0)
    }))
}

我假设,units等于原始对象中的number

result包含:

[
   {
      "date":"2017-03-06T16:48:23.080Z",
      "products":[
         {
            "product":"Product 1",
            "units":3
         },
         {
            "product":"Product 2",
            "units":2
         }
      ]
   },
   {
      "date":"2017-03-07T16:48:23.080Z",
      "products":[
         {
            "product":"Product 2",
            "units":10
         },
         {
            "product":"Product 3",
            "units":1
         }
      ]
   }
]

答案 1 :(得分:1)

您可以对哈希表使用嵌套方法,该方法反映日期和产品以便于访问。

var array = [{ doc: { date: "2017-03-06T16:48:23.080Z", products: [{ product: "Product 1", number: 3 }, { product: "Product 2", number: 2 }] } }, { doc: { date: "2017-03-07T16:48:23.080Z", products: [{ product: "Product 2", number: 10 }, { product: "Product 3", number: 1 }] } }],
    result = [],
    hash = { _: result };

array.forEach(function (a) {
    var date = a.doc.date.slice(0, 10),
        temp = hash;

    if (!temp[date]) {
        temp[date] = { _: [] };
        temp._.push({ date: date, products: temp[date]._ });
    }
    temp = temp[date];
    a.doc.products.forEach(function (b) {
        if (!temp[b.product]) {
            temp[b.product] = { product: b.product, units: 0 };
            temp._.push(temp[b.product]);
        }
        temp[b.product].units += b.number;
    });
});

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

答案 2 :(得分:0)

一个简单的算法是将结果存储到一个数组中,并在每次迭代时检查该数组中是否存在日期:

function groupByDate(array) {
    var result = [];
    for (var i = 0; i < array.length; i++) {
        var doc = array[i].doc;

        // try to find an element in the resulting array with the same date
        var group = result.find(function(element) {
            // Note: this will do string comparison up to the millisecond.
            // If you want to group by days, months or years you might need
            // to parse the dates here
            return element.doc.date == doc.date;
        }) || null;

        if (group == null) {
            // No element with the specified date was found in the resulting array =>
            // we create a new one and append it
            group = {
                doc: {
                    date: doc.date,
                    products: []
                }
            };
            result.push(group);
        }

        // push the input products to the group
        group.doc.products.push.apply(group.doc.products, doc.products);
    }

    return result;
}

然后像这样使用这个函数:

var array = ... the input array from your question ...
var reuslt = groupByDate(array);