4

サービスから、キーと値のペアを含む JSON オブジェクトを受け取ります。それらからオブジェクトを動的に作成し、1 つの列でグループ化する必要があります。

JSON は次のようになります。

[
    { "Group" : "A", "Key" : "Name", "Value" : "John" },
    { "Group" : "A", "Key" : "Age",  "Value" : "30" },
    { "Group" : "A", "Key" : "City", "Value" : "London" },
    { "Group" : "B", "Key" : "Name", "Value" : "Hans" },
    { "Group" : "B", "Key" : "Age",  "Value" : "35" },
    { "Group" : "B", "Key" : "City", "Value" : "Berlin" },
    { "Group" : "C", "Key" : "Name", "Value" : "José" },
    { "Group" : "C", "Key" : "Age",  "Value" : "25" },
    { "Group" : "C", "Key" : "City", "Value" : "Madrid" }
]

それを次のオブジェクトの配列に変換する必要があります。

[
    { Group : "A", Name : "John", Age : 30, City : "London" },
    { Group : "B", Name : "Hans", Age : 35, City : "Berlin" },
    { Group : "C", Name : "José", Age : 25, City : "Madrid" }
]

各グループには、任意の数のキーと値のペアを含めることができます。

現在、これに対する有効な解決策がありますが、それが最適かどうかはわかりません:

var items = [
    { "Group" : "A", "Key" : "Name", "Value" : "John" },
    { "Group" : "A", "Key" : "Age",  "Value" : "30" },
    { "Group" : "A", "Key" : "City", "Value" : "London" },
    { "Group" : "B", "Key" : "Name", "Value" : "Hans" },
    { "Group" : "B", "Key" : "Age",  "Value" : "35" },
    { "Group" : "B", "Key" : "City", "Value" : "Berlin" },
    { "Group" : "C", "Key" : "Name", "Value" : "José" },
    { "Group" : "C", "Key" : "Age",  "Value" : "25" },
    { "Group" : "C", "Key" : "City", "Value" : "Madrid" }
], item, record, hash = {}, results = [];

// Create a "hash" object to build up
for (var i = 0, len = items.length; i < len; i += 1) {
    item = items[i];

  if (!hash[item.Group]) {
    hash[item.Group] = {
      Group : item.Group
    };
  }
  hash[item.Group][item.Key] = item.Value;
}

// Push each item in the hash to the array
for (record in hash) {
  if(hash.hasOwnProperty(record)) {
    results.push(hash[record]);
  }
}

ここでフィドルを確認できます:http://jsbin.com/ozizom/1/

これに対するより良い解決策はありますか?

4

4 に答える 4

5

JSONレコードが常にグループで並べ替えられると仮定すると、別のアプローチがあります。

var json = [
    { "Group" : "A", "Key" : "Name", "Value" : "John" },
    { "Group" : "A", "Key" : "Age",  "Value" : "30" },
    { "Group" : "A", "Key" : "City", "Value" : "London" },
    { "Group" : "B", "Key" : "Name", "Value" : "Hans" },
    { "Group" : "B", "Key" : "Age",  "Value" : "35" },
    { "Group" : "B", "Key" : "City", "Value" : "Berlin" },
    { "Group" : "C", "Key" : "Name", "Value" : "José" },
    { "Group" : "C", "Key" : "Age",  "Value" : "25" },
    { "Group" : "C", "Key" : "City", "Value" : "Madrid" }
];

var array = [];
var previousGroup = null;

for(var i=0; i<json.length; i++) {
    var group = json[i].Group;
    if(previousGroup != group) {
        array.push({Group: group});
        previousGroup = group;
    }
    array[array.length-1][json[i].Key] = json[i].Value;
}

これが実際の例です。

于 2012-09-06T07:22:26.040 に答える
3

これは、JavaScript イディオムを使用してコード サイズを (良くも悪くも :-) 縮小するソリューションです。このソリューションは、入力値の順序に依存しません。

var values = [
  {Group: 'A', Key: 'Name', Value: 'John'},
  {Group: 'A', Key: 'Age', Value: '30'},
  {Group: 'A', Key: 'City', Value: 'London'},
  {Group: 'B', Key: 'Name', Value: 'Hans'},
  {Group: 'B', Key: 'Age', Value: '35'},
  {Group: 'B', Key: 'City', Value: 'Berlin'},
  {Group: 'C', Key: 'Name', Value: 'José'},
  {Group: 'C', Key: 'Age', Value: '25'},
  {Group: 'C', Key: 'City', Value: 'Madrid'}
];

var map = {};
values.forEach(function(value) {
  map[value.Group] = map[value.Group] || {Group: value.Group};
  map[value.Group][value.Key] = value.Value;
});

var results = Object.keys(map).map(function(key) { return map[key]; });

実際の例はhttp://jsfiddle.net/arQwwにあります。

これは、値が常にグループ別にソートされることを前提とした、私が見つけることができる最速のソリューションです。

var group, results = [];
for (var i = 0; i < values.length; ) {
  results.push({Group: group = values[i].Group});
  do {
    results.push[results.length - 1][values[i].Key] = values[i].Value;  
  } while (++i < values.length && values[i].Group == group);
}

パフォーマンスの比較はhttp://jsperf.com/vnmzcにあります。この 2 番目のソリューションは高速ですが、両方のパフォーマンスは O(n) であり、実際の違いは重要ではないため、最初のソリューションの方が単純で一般的であるため、おそらく好ましいでしょう。

于 2013-02-15T18:20:45.263 に答える
1

データを頻繁に操作する必要がある場合は、アンダースコアフレームワークをお勧めします。これは、ソリューションがどのように見えるかです。

/*
 We group items into object that looks like {group: attributes, ..}
 Then for each group we create result object denoting group,
 and extend result with object created from keys and values of attributes
*/
_.map(_.groupBy(items, function (item) {return item.Group}),
     function (attributes, group) {
        return _.extend({Group: group},
                        _.object(_.pluck(attributes, 'Key'),
                                 _.pluck(attributes, 'Value')))
    })
于 2015-03-19T04:33:50.813 に答える
-1

同様の問題で助けが必要です。値を合計したいのですが。オブジェクトを含むこの配列があります

var myArrWithObj = [
    {DateToSort: "Jul2014", ValueOneToSum: "60", ValueTwoToSum: "15"},
    {DateToSort: "Jul2014", ValueOneToSum: "30", ValueTwoToSum: "50"},
    {DateToSort: "Jul2014", ValueOneToSum: "12", ValueTwoToSum: "22"},
    {DateToSort: "Aug2014", ValueOneToSum: "65", ValueTwoToSum: "25"},
    {DateToSort: "Aug2014", ValueOneToSum: "13", ValueTwoToSum: "10"},
    {DateToSort: "Aug2014", ValueOneToSum: "90", ValueTwoToSum: "20"},
    {DateToSort: "Sep2014", ValueOneToSum: "60", ValueTwoToSum: "15"},
    {DateToSort: "Sep2014", ValueOneToSum: "60", ValueTwoToSum: "18"},
    {DateToSort: "Sep2014", ValueOneToSum: "75", ValueTwoToSum: "18"}
                   ];

オプションメニューから合計する月をユーザーに選択してもらいます。

ユーザーが選択メニューから選択した場合、に基づいてすべての値と値August 2014を合計したいのですが、どうすればそれを行うことができますか?ValueOneToSumValueTwoToSumAug2014

例: totalSumOneforAug2014は と168totalSumTwoなります55

于 2014-08-03T18:55:55.360 に答える