web-dev-qa-db-ja.com

JavaScript |オブジェクトのグループ化

オブジェクトがあります。以下のようになります:

[
  {
    "name":"Display",
    "group":"Technical detals",
    "id":"60",
    "value":"4"
  },
  {
    "name":"Manufacturer",
    "group":"Manufacturer",
    "id":"58",
    "value":"Apple"
  },
  {
    "name":"OS",
    "group":"Technical detals",
    "id":"37",
    "value":"Apple iOS"
  }
]

このデータをグループフィールドでグループ化して、このオブジェクトを取得します。

var obj = {
    0 = [
    {
       'group'   = 'Technical detals',
       'name'    = 'Display',
       'id'      = '60',
       'value'   = '4'
    },
    {
       'group'   = 'Technical detals',
       'name'    = 'OS',
       'id'      = '37',
       'value'   = 'Apple iOS'
    }],
    1   = [
    {
       'group'   = 'Manufacturer',
       'name'    = 'Manufacturer',
       'id'      = '58',
       'value'   = 'Apple'
    }]
}

最初のオブジェクトをどのようにグループ化できますか?

15
XTRUST.ORG

次のようなもので試してください:

function groupBy(collection, property) {
    var i = 0, val, index,
        values = [], result = [];
    for (; i < collection.length; i++) {
        val = collection[i][property];
        index = values.indexOf(val);
        if (index > -1)
            result[index].Push(collection[i]);
        else {
            values.Push(val);
            result.Push([collection[i]]);
        }
    }
    return result;
}

var obj = groupBy(list, "group");

それを念頭に置いて Array.prototype.indexOfはIE8以前では定義されていませんが、一般的なポリフィルがあります。

21
MaxArt

アプリケーションでunderscore.jsを使用している場合は、次の操作を行うだけです。

var groups = _.groupBy(data, 'group'); // data is your initial collection

または、ライブラリを使用したくない場合は、自分で実行できます。

var groups = { };
data.forEach(function(item){
   var list = groups[item.group];

   if(list){
       list.Push(item);
   } else{
      groups[item.group] = [item];
   }
});

両方の例を実際に見ることができます http://jsfiddle.net/nkVu6/3/

11
ppoliani

ES6 Mapを使用したい場合は、次のようにします。

function groupBy(arr, prop) {
    const map = new Map(Array.from(arr, obj => [obj[prop], []]));
    arr.forEach(obj => map.get(obj[prop]).Push(obj));
    return Array.from(map.values());
}

const data = [{ name: "Display", group: "Technical detals", id: 60, value: 4 }, { name: "Manufacturer", group: "Manufacturer", id: 58, value: "Apple" }, { name: "OS", group: "Technical detals", id: 37, value: "Apple iOS" }];
        
console.log(groupBy(data, "group"));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Mapインスタンスは、入力配列から生成されたキーと値のペアから作成されます。キーはグループ化するプロパティの値であり、値は空の配列として初期化されます。

次に、それらのアレイにデータが入力されます。最後に、マップの値(つまり、入力された配列)が返されます。

11
trincot

Reduce は、このような状況に最適です。以下のlistが入力データです。

const list = [{
    'name': 'Display',
    'group': 'Technical detals',
    'id': '60',
    'value': '4'
  },
  {
    'name': 'Manufacturer',
    'group': 'Manufacturer',
    'id': '58',
    'value': 'Apple'
  },
  {
    'name': 'OS',
    'group': 'Technical detals',
    'id': '37',
    'value': 'Apple iOS'
  }
];

const groups = list.reduce((groups, item) => {
  const group = (groups[item.group] || []);
  group.Push(item);
  groups[item.group] = group;
  return groups;
}, {});

console.log(groups);

そして、不変になりたい場合は、次のようにreduceを書くことができます。

const list = [{
    'name': 'Display',
    'group': 'Technical detals',
    'id': '60',
    'value': '4'
  },
  {
    'name': 'Manufacturer',
    'group': 'Manufacturer',
    'id': '58',
    'value': 'Apple'
  },
  {
    'name': 'OS',
    'group': 'Technical detals',
    'id': '37',
    'value': 'Apple iOS'
  }
];

const groups = list.reduce((groups, item) => ({
  ...groups,
  [item.group]: [...(groups[item.group] || []), item]
}), {});

console.log(groups);

環境でスプレッド構文が許可されているかどうかによって異なります。

7
btomw

グループと Array#forEach 配列を繰り返すため。

次に、ハッシュが存在するかどうかを確認し、存在しない場合は空の配列を割り当てて、結果セットにプッシュします。

後で実際の要素をハッシュの配列にプッシュします。

function groupBy(array, group) {
    var hash = Object.create(null),
        result = [];

    array.forEach(function (a) {
        if (!hash[a[group]]) {
            hash[a[group]] = [];
            result.Push(hash[a[group]]);
        }
        hash[a[group]].Push(a);
    });
    return result;
}

var data = [{ name: "Display", group: "Technical detals", id: 60, value: 4 }, { name: "Manufacturer", group: "Manufacturer", id: 58, value: "Apple" }, { name: "OS", group: "Technical detals", id: 37, value: "Apple iOS" }];
        
console.log(groupBy(data, "group"));
.as-console-wrapper { max-height: 100% !important; top: 0; }
7
Nina Scholz

reduce および filter を使用します。

最初の配列がdataに割り当てられているとしましょう

data.reduce((acc, d) => {
    if (Object.keys(acc).includes(d.group)) return acc;

    acc[d.group] = data.filter(g => g.group === d.group); 
    return acc;
}, {})

これはあなたに何かを与えるでしょう

{
    "Technical detals" = [
    {
       'group'   = 'Technical detals',
       'name'    = 'Display',
       'id'      = '60',
       'value'   = '4'
    },
    {
       'group'   = 'Technical detals',
       'name'    = 'OS',
       'id'      = '37',
       'value'   = 'Apple iOS'
    }],
    "Manufacturer"   = [
    {
       'group'   = 'Manufacturer',
       'name'    = 'Manufacturer',
       'id'      = '58',
       'value'   = 'Apple'
    }]
}
2
Anthony Awuley

承認済みとマークされた回答を使用しようとしましたが、評価されているプロパティのタイプによっては、一部のグループで欠落している要素があることに気付きました。これはその答えから導き出された解決策です:

function groupBy(collection, property) {
  var i = 0, values = [], result = [];
  for (i; i < collection.length; i++) {
    if(values.indexOf(collection[i][property]) === -1) {
      values.Push(collection[i][property]);
      result.Push(collection.filter(function(v) { return v[property] === collection[i][property] }));
    }
  }
  return result;
}
var obj = groupBy(list, "group");
0
buffolander

試す

let g = (d,h={},r={},i=0)=>(d.map(x=>(y=x.group,h[y]?1:(h[y]=++i,r[h[y]-1]=[]),r[h[y]-1].Push(x))),r);
console.log( g(data) );
let data=[
  {
    "name":"Display",
    "group":"Technical detals",
    "id":"60",
    "value":"4"
  },
  {
    "name":"Manufacturer",
    "group":"Manufacturer",
    "id":"58",
    "value":"Apple"
  },
  {
    "name":"OS",
    "group":"Technical detals",
    "id":"37",
    "value":"Apple iOS"
  }
];


let g = (d,h={},r={},i=0)=>(d.map(x=>(y=x.group,h[y]?1:(h[y]=++i,r[h[y]-1]=[]),r[h[y]-1].Push(x))),r);

console.log(g(data));
0

Lodashを使用している場合は、 groupBy を使用できます。

配列とオブジェクトの両方をサポートしています。

例:

_.groupBy([6.1, 4.2, 6.3], Math.floor);
// => { '4': [4.2], '6': [6.1, 6.3] }

// The `_.property` iteratee shorthand.
_.groupBy(['one', 'two', 'three'], 'length');
// => { '3': ['one', 'two'], '5': ['three'] }
0
Hongbo Miao