Sum Object属性适用于javascript中的另一个属性

时间:2017-09-29 13:08:17

标签: javascript typescript

我有一个与此类似的对象:

[
  {
    origin: "XX",
    destination: "YY",
    volume: 500
  },
  {
    origin: "ZZ",
    destination: "YY",
    volume: 500
  }
]

我想制作地图并减少这些对象以获取某个属性的卷总和,在我的情况下为目的地。

所以我希望得到类似的东西:

 [
   {
     destination: "YY",
     volume: 1000
   }
]

谢谢。

3 个答案:

答案 0 :(得分:0)

试试这个;

var array = [{
    origin: "XX",
    destination: "YY",
    volume: 500
  },
  {
    origin: "ZZ",
    destination: "YY",
    volume: 500
  }
];

function sumFn(a, propType, propVal) {
  var i = 0;
  array.forEach(function(a) {
    if (a[propType] && a[propType] === propVal) {
      i += a.volume;
    }
  });
  console.log({
    [propType]: propVal,
    volume: i
  });
}

sumFn(array, "destination", "YY");

答案 1 :(得分:0)

您尝试按destination属性对数组进行分组。这里是TypeScript中的一般groupBy函数,它创建Map(ES2015或更高版本,如果需要,可以使用polyfill,如果您知道值将始终是字符串属性,则替换为普通对象)从destination值到具有destination的值的对象数组:

function groupBy<T, K extends keyof T>(key: K, arr: T[]): Map<T[K], T[]> {
  const map = new Map<T[K], T[]>();
  arr.forEach(t => {
    if (!map.has(t[key])) {
      map.set(t[key], []);
    }
    map.get(t[key])!.push(t);
  })
  return map;
}

然后,根据您的意见,

const input = [
  {
    origin: "XX",
    destination: "YY",
    volume: 500
  },
  {
    origin: "ZZ",
    destination: "YY",
    volume: 500
  }
]

您可以将分组Map的条目数组映射到包含组destination的对象数组和每个组的volume之和:

const output = Array.from(groupBy("destination", input).entries())
  .map(([dest, objs]) => ({
    destination: dest,
    volume: objs.reduce((acc, cur) => acc + cur.volume, 0)
  }))

console.log(JSON.stringify(output)); // produces the desired output

希望有所帮助;祝你好运!

它适用于我今天使用v2.5.1的in the TypeScript Playground

答案 2 :(得分:0)

如果使用Array.reduce的强大功能,则甚至可以提供与任何数据结构无关的通用基本收集器方法,但使用它的第一个collectoraccumulator参数来承载数据oder中特定于结构的getter / setter功能,用于操作此特定数据。

正确操作OP给定示例代码的实现可能看起来类似于以下代码......

var dataList = [{

    origin: "XX",
    destination: "YY",
    volume: 500
}, {
    origin: "ZZ",
    destination: "YY",
    volume: 500
}, {
    origin: "XX",
    destination: "AA",
    volume: 200
}, {
    origin: "ZZ",
    destination: "AA",
    volume: 100
}];

function collectSourceValueConnectedTargetSummaries(collector, dataItem) {  // a generic data structure agnostic summary approach ...
    var registry    = collector.registry;
    var sourceValue = collector.getSourceValue(dataItem);
    var summaryItem = registry[sourceValue];

    if (!summaryItem) {
        summaryItem = registry[sourceValue] = Object.assign({}, collector.summaryItem);

        collector.putSummarySource(summaryItem, sourceValue);
        collector.summaryList.push(summaryItem);
    }
    collector.summarizeTarget(summaryItem, collector.getTargetValue(dataItem));

    return collector;
}

var result = dataList.reduce(collectSourceValueConnectedTargetSummaries, {  // ... that makes use of data structure specific methods.

    registry: {},

    // this two methods just read data and their's implementation reflects the data structure that gets operated.
    getSourceValue:     function (dataItem) { return dataItem.destination },
    getTargetValue:     function (dataItem) { return dataItem.volume },

    // the next two methods do control the mapping process (the output) of all summary data.
    putSummarySource:   function (summaryItem, value) { summaryItem.destination = value; },
    summarizeTarget:    function (summaryItem, value) { summaryItem.volume = (summaryItem.volume + value); },

    summaryItem:  { /*destination: '', */volume: 0 },
    summaryList: []

}).summaryList;

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