如何迭代和合并javascript数组

时间:2015-07-31 13:12:58

标签: javascript json object

我有一个看起来像这样的JavaScript对象。它基本上是我从某个API获得的输出。该对象的结构使得它可以包含多个相同'权益的实例。 (见下面的Hitachi Home):

  {
    "results": {
      "holdings": [{
        "equity": {
          "text": "Hitachi Home"
        },
        "holding_pc": "6.48",
        "sector": "Consumer Durables",
        "shares_no": "1537.00",
        "value_cr": "0.24"
      }, {
        "equity": {
          "text": "Mahindra CIE"
        },
        "holding_pc": "6.34",
        "sector": "Manufacturing",
        "shares_no": "10376.00",
        "value_cr": "0.24"
      }, {
        "equity": {
          "text": "Schneider Infra"
        },
        "holding_pc": "5.33",
        "sector": "Utilities",
        "shares_no": "9518.00",
        "value_cr": "0.20",
      }, {
        "equity": {
          "text": "Hitachi Home"
        },
        "holding_pc": "2.18",
        "sector": "Consumer Durables",
        "shares_no": "437.00",
        "value_cr": "0.12"
      }]
    }
  }

编写将整个对象作为输入的JavaScript函数的最佳方法是什么,迭代所有记录并合并它以使具有相同'权限的记录总结和巩固。例如,在产出中,股权' Hitachi Home'应该看起来像这样:

  {
    "results": {
      "holdings": [{
        "equity": {
          "text": "Hitachi Home"
        },
        "holding_pc": "8.66",
        "sector": "Consumer Durables",
        "shares_no": "1974.00",
        "value_cr": "0.36"
      }, {
        "equity": {
          "text": "Mahindra CIE"
        },
        "holding_pc": "6.34",
        "sector": "Manufacturing",
        "shares_no": "10376.00",
        "value_cr": "0.24"
      }, {
        "equity": {
          "text": "Schneider Infra"
        },
        "holding_pc": "5.33",
        "sector": "Utilities",
        "shares_no": "9518.00",
        "value_cr": "0.20",
      }]
    }
  }

基本上,我正在尝试编写一个JS函数,它将使用相同的文本汇总所有股票。以下是我们的主要目标:

function transform(data) {
  function sumHoldings(row) {
    newrow = {};
    newrow.equity = row.equity.text;
    newrow.holding_pc = row.holding_pc;
    return newrow;
  }
  for(var holdings in data.results) {
    data.results.total_holdings = data.results.holdings.map(sumHoldings);
  };

  return data;
}

4 个答案:

答案 0 :(得分:1)

我建议制作一个可以合并数据的馆藏对象,并且可以通过馆藏名称访问(我认为这里是独一无二的)。

通过这种方式,您可以遍历您的馆藏阵列并将原始对象的数据分配给新对象,通常如下所示:

    var consolidatedHoldings = {};

    obj.results.holdings.forEach(function(holding){
        holding.forEach(function (holdingDataValue, holdingDataIndex) {
            // checking if the value is a number
            if (!isNaN(parseFloat(holdingDataValue)) && isFinite(holdingDataValue)) {
                consolidatedHoldings[holdingDataIndex] = consolidatedHoldings[holdingDataIndex] + parseFloat(holdingDataValue);
            } else {
                consolidatedHoldings[holdingDataValue] = holdingDataValue;
            }
        });
    });

这样,如果密钥不存在,它就会被创建。如果它被覆盖(预期具有相同的值)。如果这是一个数字,它会被添加。

您最终得到一个合并的馆藏对象,然后您可能想要变成一个阵列并放入原始对象。

答案 1 :(得分:1)

var map = {};

a.holdings.forEach(function(holding){  
   var text = holding.equity.text;
   var entry = map[text] || (map[text] = []);

   entry.push(holding);
});

Object.keys(map).map(function(key) {
  var values = map[key];
  var parseFloats = function(a, b) { return parseFloat(a) + parseFloat(b); };

  return {
     equity: {
        "text" : key
     },
     sector : values[0].sector,
     value_cr: values.map(function(e) { return e.value_cr; }).reduce(parseFloats, 0), 
     shares_no: values.map(function(e) { return e.shares_no; }).reduce(parseFloats, 0), 
     holding_pc : values.map(function(e) { return e.holding_pc; }).reduce(parseFloats, 0)
   }
});

答案 2 :(得分:1)

您可以按如下方式缩小原始数组:

var obj = {
  "results": {
    "holdings": [{
      "equity": {
        "text": "Hitachi Home"
      },
      "holding_pc": "6.48",
      "sector": "Consumer Durables",
      "shares_no": "1537.00",
      "value_cr": "0.24"
    }, {
      "equity": {
        "text": "Mahindra CIE"
      },
      "holding_pc": "6.34",
      "sector": "Manufacturing",
      "shares_no": "10376.00",
      "value_cr": "0.24"
    }, {
      "equity": {
        "text": "Schneider Infra"
      },
      "holding_pc": "5.33",
      "sector": "Utilities",
      "shares_no": "9518.00",
      "value_cr": "0.20",
    }, {
      "equity": {
        "text": "Hitachi Home"
      },
      "holding_pc": "2.18",
      "sector": "Consumer Durables",
      "shares_no": "437.00",
      "value_cr": "0.12"
    }]
  }
}

function findFirst(items, predicate) {
  for (var i = 0; i < items.length; i++) {
    if (predicate(items[i])) {
      return items[i];
    }
  }
  return null;
}

var result = obj.results.holdings.reduce(function (arr, it) {
  it.holding_pc = Number(it.holding_pc);
  it.shares_no = Number(it.shares_no);
  it.value_cr = Number(it.value_cr);
  var holding = findFirst(arr, function (_it) { return _it.equity.text === it.equity.text });
  if (holding) {
    // If item is found make calculations
    holding.holding_pc += it.holding_pc;
    holding.shares_no += it.shares_no;
    holding.value_cr += it.value_cr;
  } else {
    // If item is not found aded to the array
    arr.push(it);
  }
  return arr;
}, []);


document.querySelector('#out').innerHTML = JSON.stringify({ results: { holdings: result } }, undefined, 4);
<pre id="out"></pre>

答案 3 :(得分:0)

您应该迭代数组,而不是对象。除非您对迭代对象的属性感兴趣。类似的东西:

obj.results.holdings.forEach(function(holding){
    //holding.equity.text holds the equity string.
    //It's up to you how to deal with the uniqueness.
    //You could just push it into an array if the equity.text value isn't within the array.
});

编辑:我想你想要减少数组,而不是找到唯一的。

var equity = { };
var sums = ['holding_pc', 'shares_no', 'value_cr'];
var holdings = obj.results.holdings.reduce(function(previousValue, currentValue){
    var currentEquity = currentValue.equity.text;
    if(equity[currentEquity] !== undefined){
        //Equity exists in reduced array
        oldObj = previousValue[equity[currentEquity]];
        sums.forEach(function(prop){
           oldObj[prop] = Number(oldObj[prop]) + Number(currentValue[prop]); 
        });
    } else {
      //Equity doesn't exist
        equity[currentEquity] = previousValue.length;
        previousValue.push(currentValue);
    }
    return previousValue;
}, []);
//holdings is now a reduced array (not the result object, result.holdings array).