如何总结这个对象数组?

时间:2018-09-05 15:51:39

标签: javascript arrays

我有一个代表产品的对象数组,我想基于多个其他属性的值来总结数量值。例如:

[
{
  "title": "House Coffee",
  "weight": "1kg",
  "grind": "filter",
  "quantity": 5
},
{
  "title": "House Coffee",
  "weight": "1kg",
  "grind": "filter",
  "quantity": 5
},
{
  "title": "House Coffee",
  "weight": "250g",
  "grind": "Whole Beans",
  "quantity": 4
},
{
  "title": "House Coffee",
  "weight": "250g",
  "grind": "Whole Beans",
  "quantity": 2
}
]

如果title weightgrind的所有三个属性都是 相同 ,我想减少数量,以便这种情况下,我将得到一个新的数组,如:

[
{
  "title": "House Coffee",
  "weight": "1kg",
  "grind": "filter",
  "quantity": 10
},
{
  "title": "House Coffee",
  "weight": "250g",
  "grind": "Whole Beans",
  "quantity": 6
},
]

5 个答案:

答案 0 :(得分:2)

您需要迭代数组并根据已处理的内容进行比较。进行迭代时,请跟踪尚未“减少”的内容。如果您已有符合条件的匹配项,请更新跟踪的项目。

对于您的情况,您需要为每个冲泡保留一个新阵列。迭代时,如果您的新数组中已经有该商品(基于匹配的标题,重量和研磨度),则更新数量。否则,您推送新项目:

//const assert = require("assert");

const given = [{
    "title": "House Coffee",
    "weight": "1kg",
    "grind": "filter",
    "quantity": 5
  },
  {
    "title": "House Coffee",
    "weight": "1kg",
    "grind": "filter",
    "quantity": 5
  },
  {
    "title": "House Coffee",
    "weight": "250g",
    "grind": "Whole Beans",
    "quantity": 4
  },
  {
    "title": "House Coffee",
    "weight": "250g",
    "grind": "Whole Beans",
    "quantity": 2
  }
];

const expected = [{
    "title": "House Coffee",
    "weight": "1kg",
    "grind": "filter",
    "quantity": 10
  },
  {
    "title": "House Coffee",
    "weight": "250g",
    "grind": "Whole Beans",
    "quantity": 6
  }
];

function comparator(a, b) {
  return (
    a.title === b.title &&
    a.weight === b.weight &&
    a.grind === b.grind
  );
}

function doStuff(arr) {
  const reduced = [];
  arr.forEach(i => {
    const index = reduced.findIndex(e => comparator(e, i));
    if (index < 0) {
      reduced.push(Object.assign({}, i));
    } else {
      reduced[index].quantity += i.quantity;
    }
  });
  return reduced;
}

//assert.deepEqual(doStuff(given), expected);

console.log(doStuff(given));

答案 1 :(得分:2)

您可以尝试这样的事情:

function summarizeArray(arr)    {
    var result = [];
    for(var i = 0; i < arr.length; i++) {
        var added = false;
        for(var j = 0; j < result.length; j++)  {
            if((result[j].title == arr[i].title) && (result[j].weight == arr[i].weight) && (result[j].grind == arr[i].grind))   {
                added = true;
                result[j].quantity += arr[i].quantity;
                break;
            }
        }
        if(!added)  {
            result.push(arr[i]);
        }
    }
    return result;
}

基本上,它只是基于第一个构建第二个数组,但是在添加每个项目之前先进行搜索。如果找到匹配项,则将合并权重,而不仅仅是添加对象。 http://jsfiddle.net/7hza2kxf/

答案 2 :(得分:1)

您可以使用所需属性值的组合键进行分组。

var data = [{ title: "House Coffee", weight: "1kg", grind: "filter", quantity: 5 }, { title: "House Coffee", weight: "1kg", grind: "filter", quantity: 5 }, { title: "House Coffee", weight: "250g", grind: "Whole Beans", quantity: 4 }, { title: "House Coffee", weight: "250g", grind: "Whole Beans", quantity: 2 }],
    keys = ['title', 'grind', 'weight'],
    result = Array.from(
        data
            .reduce((m, o) => {
                var key = keys.map(k => o[k]).join('|');
                if (!m.has(key)) {
                    return m.set(key, Object.assign({}, o));
                }
                m.get(key).quantity += o.quantity;
                return m;
            }, new Map)
            .values()
    );

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

答案 3 :(得分:1)

快速的数据结构在此处为HashMap。这是一个具有O(1)查找复杂度的简单json。

PsuedoCode

1. Traverse through the given array.
2. Compare the concatenated string with keys of the map.
3. If key is already present in the map, 
    - Add the quantity value.
4. If key is NOT present in the map, 
    - Add the concatenated string as new key in map. 
5. Convert map to an array

concatenated string - concatenate values of the required keys(title, weight, and grind) into a string. This string is added as key in the map, to check for duplicate values.

代码段O(n)

var array = [{"title":"House Coffee","weight":"1kg","grind":"filter","quantity":5},{"title":"House Coffee","weight":"1kg","grind":"filter","quantity":5},{"title":"House Coffee","weight":"250g","grind":"Whole Beans","quantity":4},{"title":"House Coffee","weight":"250g","grind":"Whole Beans","quantity":2}];
var map = {};
var key, keys;
var summary = [];

array.forEach(function(elem) {
    key = elem.title + '-' + elem.weight +  '-' + elem.grind;

    if (map[key]) {
        map[key] += elem.quantity;
    } else {
        map[key] = elem.quantity;
    }
});

for (var key in map){
    keys = key.split('-');

    summary.push({
       "title": keys[0],
       "weight": keys[1],
       "grind": keys[2],
       "quantity": map[key]
    });
}

console.log('summary: ', summary);

答案 4 :(得分:-1)

您可以尝试使用过滤器,映射和归约功能。在这里https://codeburst.io/javascript-learn-to-chain-map-filter-and-reduce-acd2d0562cd4

否则,您可以创建一个空数组,并遍历对象数组,并检查对象是否已添加到新数组中(如果没有,则添加)。如果已经添加,则求和新的数量,等等。

工作示例:

@click:append