合并多个对象数组并将重复值javascript加起来

时间:2017-03-21 05:37:33

标签: javascript arrays

我有多个数组,看起来像这样

第一个对象数组看起来像这样

Array[4]

    0 : Object
        price:"2"       
        ref:"A"
    1 : Object
        price:"20"
        ref:"B"
    2 : Object
        price:"23"      
        ref:"C"
    3 : Object
        price:"23"      
        ref:"D"     

第二个对象数组看起来像这样

Array[4]

    0 : Object
        price:"12"      
        ref:"A"
    1 : Object
        price:"5"       
        ref:"B"
    2 : Object
        price:"23"      
        ref:"E"
    3 : Object
        price:"23"      
        ref:"F" 

我的第三个对象看起来像这样。

Array[2]

0 : Object
    name:"Blah"     
    fcp:"erol"
1 : Object
    name:"Blah2"        
    fcp:"tpep"

现在我想根据priceref求和。第一个对象和第二个对象具有参考A和B的共同点。这样最终的对象看起来像

Array[7]

    0 : Object
        price:"14"      
        ref:"A"
    1 : Object
        price:"25"
        ref:"B"
    2 : Object
        price:"23"      
        ref:"C"
    3 : Object
        price:"23"      
        ref:"D" 
    4 : Object
        price:"23"      
        ref:"E"
    5 : Object
        price:"23"      
        ref:"F" 
    6 : Object
        name:"Blah"     
        fcp:"erol"
    7 : Object
        name:"Blah2"        
        fcp:"tpep"  

2 个答案:

答案 0 :(得分:5)

您可以使用reduce功能进行抓取

var array1 = [{
    price: "2",
    ref: "A"
  },
  {
    price: "20",
    ref: "B"
  },
  {
    price: "23",
    ref: "C"
  },
  {
    price: "23",
    ref: "D"
  }
];

var array2 = [{
    price: "12",
    ref: "A"
  },
  {
    price: "5",
    ref: "B"
  },
  {
    price: "23",
    ref: "E"
  },
  {
    price: "23",
    ref: "F"
  }
];

var array3 = [{
    name: "Blah",
    fcp: "erol"
  },
  {
    name: "Blah2",
    fcp: "tpep"
  }
];

var result = array1.concat(array2, array3).reduce(function(acc, curr) {
  if (curr.ref) {
    var fromMap = acc.map[curr.ref];
    if (!fromMap) {
      acc.map[curr.ref] = fromMap = {
        price: 0,
        ref: curr.ref
      }
      acc.result.push(fromMap);
    }
    fromMap.price += parseFloat(curr.price);
  } else {
    acc.result.push(curr);
  }
  return acc;
}, {
  map: {},
  result: []
}).result;

console.log(result);

答案 1 :(得分:0)

<强>更新

我稍微调整了以前解决方案中的代码,使其以线性时间O(n)运行,通过维护“hashmap”使其稍微快一点。对于原始问题中给定大小的数组,性能增强将为零,但它仍然是更快的解决方案。

// concat all items of all arrays into a big array
var bigArray = [].concat(array1, array2, array3);

// maintain a hashmap to track if "ref" exists at any index in any previous obj of array
// key=ref,  value=index-where-ref-exists
var hash = {};

// loop over bigArray
for (var i = 0; i < bigArray.length; i++) {
  // current obj we are processing
  var currObj = bigArray[i];
  // change price to number format
  var priceInNumberFormat = parseFloat(currObj.price);

  // if price is not a valid number, move onto processing next obj
  if (!isNumber(priceInNumberFormat)) {
    continue;
  }

  // update currentObj's "price" property. We need it to be in number format so we could do addition
  currObj.price = priceInNumberFormat;

  // check if any obj exits with same ref value.
  if (hash[currObj.ref] !== undefined) {
    var idx = hash[currObj.ref];          // index of existing obj with same "ref"
    bigArray[idx].price += currObj.price;
    bigArray.splice(i, 1);

    // backtrack on "i" value since we shortened the length of the array
    i--;
  } else {
    hash[currObj.ref] = i;
  }
}

以前的解决方案:

以下是一种可能的解决方案:

var array1 = [
  { price:"2", ref:"A" },
  { price:"20", ref:"B" },
  { price:"23", ref:"C" },
  { price:"23", ref:"D" }
];

var array2 = [
  { price:"12", ref:"A" },
  { price:"5", ref:"B" },
  { price:"23", ref:"E" },
  { price:"23", ref:"F" }
];

var array3 = [
  { name:"Blah", fcp:"erol" },
  { name:"Blah2", fcp:"tpep" }
];

// helper function to determine if a arg is valid number
function isNumber (num) {
  return (typeof num === 'number' && !isNaN(num));
}

// concat all items of all arrays into a big array
var bigArray = [].concat(array1, array2, array3);

// loop over bigArray
for (var i = 0; i < bigArray.length; i++) {
  // current obj we are processing
  var currObj = bigArray[i];
  // change price to number format
  var iPriceInNumberFormat = parseFloat(currObj.price);

  // if price is not a valid number, move onto processing next obj
  if (!isNumber(iPriceInNumberFormat)) {
    continue;
  }

  // update currentObj's "price" property. We need it to be in number format so we could do addition
  currObj.price = iPriceInNumberFormat;

  // now loop over remaining items of bigArray
  for (var j = i+1; j < bigArray.length; j++) {
    // if there is another object further down bigArray with same "ref" value as currObj
    if (currObj.ref === bigArray[j].ref) {
      // convert its price to number format as well
      var jPriceInNumberFormat = parseFloat(bigArray[j].price);

      // if its not a valid number, move onto next obj
      if (!isNumber(jPriceInNumberFormat)) {
        continue;
      }

      // otherwise add its price value to currObj's price
      currObj.price += jPriceInNumberFormat;

      // since we have added the price of this obj, discard it. 
      // remove bigArray[j] from bigArray
      bigArray.splice(j, 1);
    }
  }
}

// now bigArray has removed all objects with duplicate "ref" values, and has their prices added
console.log(bigArray);

// should print bigArray value as expected solution:

// [ { price: 14, ref: 'A' },
//  { price: 25, ref: 'B' },
//  { price: 23, ref: 'C' },
//  { price: 23, ref: 'D' },
//  { price: 23, ref: 'E' },
//  { price: 23, ref: 'F' },
//  { name: 'Blah', fcp: 'erol' },
//  { name: 'Blah2', fcp: 'tpep' } ]