2

次のオブジェクトの配列があるとします。

dataArray = [ 
  { id: "a", score: 1 }, 
  { id: "b", score: 2 }, 
  { id: "c", score: 5 }, 
  ...
  { id: "a", score: 3 },
  ...
  { id: "c", score: 2},
  ...
 ]

次のようなresultArrayを取得するにはどうすればよいですか:

resultArray = [
  { id: "a", score: sum of all the scores when id is a },
  { id: "b", score: sum of all the scores when id is b },
  ...
  ...
]
4

5 に答える 5

2

アンダースコア ライブラリを使用する場合:

_.map  _.groupBy(dataArray, 'id'), (v, k) -> 
    {id: k, score: _.reduce(v, ((m, i) -> m + i['score']), 0) }
于 2013-03-15T21:33:39.060 に答える
1

アンダースコア バージョンは、おそらく最も簡潔です。これは単純な CoffeeScript バージョンで、補助オブジェクトを 1 つだけ作成して ID による高速アクセスを行い、全体を O(n) にします。

aggregateScores = (dataArr) ->
  scores = {}
  for {id, score} in dataArr
    scores[id] = (scores[id] or 0) + score
  {id, score} for id, score of scores

console.log aggregateScores [ 
  { id: "a", score: 1 }
  { id: "b", score: 2 } 
  { id: "c", score: 5 } 
  { id: "a", score: 3 }
  { id: "c", score: 2 }
 ]
 # Output:
 # [{id:"a", score:4}, {id:"b", score:2}, {id:"c", score:7}]
于 2013-03-15T22:56:36.927 に答える
0

これは単純な coffeescript バージョンです。

data = [
  { id: "a", score: 1 }
  { id: "b", score: 2 }
  { id: "a", score: 5 }
  { id: "c", score: 2 }
  { id: "b", score: 3 }
]

# Aggregate scores in a map.
resultSet = {}
for obj in data
  resultSet[obj.id] ?= 0
  resultSet[obj.id] += obj.score
console.log resultSet

# Create array from map.
resultArr = for key, val of resultSet
  { id: key, score: val}
console.log resultArr

出力は次のとおりです。

{ a: 6, b: 5, c: 2 }
[ { id: 'a', score: 6 },
  { id: 'b', score: 5 },
  { id: 'c', score: 2 } ]

アンダースコア内の関数を使用してより洗練されたソリューションを作成できると確信していますが、coffeescript ソリューションは悪くないので、理解しやすいものを選びました。

于 2013-03-15T21:18:51.173 に答える
0

これは単純な JavaScript ですが、質問に対する長い回答は次のとおりです。

function aggregate(values, init, keyGetter, valueGetter, aggregator) {
        var results = {}
        for (var index = 0; index != values.length; ++index) {
            var value = values[index]
            var key = keyGetter(value)
            var soFar;
            if (key in results) {
                soFar = results[key]
            } else {
                soFar = init
            }
            value = valueGetter(value)
            results[key] = aggregator(soFar, value)
        }
        return results
    }

    var array = [
        { id: 'a', score: 1 },
        { id: 'b', score: 2 },
        { id: 'c', score: 5 },
        { id: 'a', score: 3 },
        { id: 'c', score: 2 }
    ]

    function keyGetter(value) {
        return value.id
    }

    function valueGetter(value) {
        return value.score
    }

    function aggregator(sum, value) {
        return sum + value
    }

    function ready() {
        var results = aggregate(array, 0, keyGetter, valueGetter, aggregator)
        console.info(results)
    }
于 2013-03-15T20:44:15.137 に答える
0

これが唯一の集計である場合は少しやり過ぎですが、Lumenizeと呼ばれる適切に文書化された集計ライブラリがあります。これは、より高度なピボット テーブル、n 次元キューブ、階層的なロールに加えて、このような単純なグループ化操作を行います。 ups、およびタイムゾーンの正確な時系列集計。

これは、Lumenize ソリューションのjsFiddleです。

node.js で試してみたい場合:

npm install Lumenize --save

次に、これをlumenizeGroupBy.coffeeという名前のファイルに入れます:

lumenize = require('Lumenize')
dataArray = [
  { id: "a", score: 1 },
  { id: "b", score: 2 },
  { id: "c", score: 5 },
  { id: "a", score: 3 },
  { id: "c", score: 2}
]

dimensions = [{field:'id'}]
metrics = [{field: 'score', f: 'sum', as: 'sum'}]
config = {dimensions, metrics}

cube = new lumenize.OLAPCube(config, dataArray)
console.log(cube.toString(null, null, 'sum'))

そして走る

coffee lumenizeGroupBy.coffee
于 2013-03-16T13:06:10.110 に答える