最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Turn groups into concat of arrays javascript - Stack Overflow

programmeradmin0浏览0评论

I have managed to split an array into separate groups based on key value. What I want to achieve is to turn these groups which can be more or less into an array, so my groups bee [[Regio__c],[Categorie__c]] instead of {Regio__c:[],Categorie__c:[]}. This with plain javascript no libraries.

I tried: return [key].concat.split; this returns undefined.

Below is my code in a snippet

var filter = [{
    "Id": "120",
    "arrayPicklist": "Categorie__c"
  }, {
    "Id": "121",
    "arrayPicklist": "Regio__c"
  },
  {
    "Id": "122",
    "arrayPicklist": "Categorie__c"
  }, {
    "Id": "123",
    "arrayPicklist": "Regio__c"
  },
  {
    "Id": "121",
    "arrayPicklist": "Regio__c"
  }
]


function splitArrayByValue(arr, key) {
  var split = {};
  for (var i = 0; i < arr.length; i++) {
    var p = arr[i][key];
    if (!split[p]) {
      split[p] = [];
    }
    split[p].push(arr[i])
  }
  return split;
}


var buckets2 = splitArrayByValue(filter, 'arrayPicklist');

console.log(buckets2);

I have managed to split an array into separate groups based on key value. What I want to achieve is to turn these groups which can be more or less into an array, so my groups bee [[Regio__c],[Categorie__c]] instead of {Regio__c:[],Categorie__c:[]}. This with plain javascript no libraries.

I tried: return [key].concat.split; this returns undefined.

Below is my code in a snippet

var filter = [{
    "Id": "120",
    "arrayPicklist": "Categorie__c"
  }, {
    "Id": "121",
    "arrayPicklist": "Regio__c"
  },
  {
    "Id": "122",
    "arrayPicklist": "Categorie__c"
  }, {
    "Id": "123",
    "arrayPicklist": "Regio__c"
  },
  {
    "Id": "121",
    "arrayPicklist": "Regio__c"
  }
]


function splitArrayByValue(arr, key) {
  var split = {};
  for (var i = 0; i < arr.length; i++) {
    var p = arr[i][key];
    if (!split[p]) {
      split[p] = [];
    }
    split[p].push(arr[i])
  }
  return split;
}


var buckets2 = splitArrayByValue(filter, 'arrayPicklist');

console.log(buckets2);

Share edited Mar 23, 2018 at 18:45 CRice 32.3k5 gold badges61 silver badges73 bronze badges asked Mar 23, 2018 at 18:29 ThomasThomas 1811 silver badge10 bronze badges 0
Add a ment  | 

6 Answers 6

Reset to default 2

You almost there, you need to get the values. An alternative is using the function Object.values

var filter = [{    "Id": "120",    "arrayPicklist": "Categorie__c"  }, {    "Id": "121",    "arrayPicklist": "Regio__c"  },  {    "Id": "122",    "arrayPicklist": "Categorie__c"  }, {    "Id": "123",    "arrayPicklist": "Regio__c"  },  {    "Id": "121",    "arrayPicklist": "Regio__c"  }]

function splitArrayByValue(arr, key) {
  var split = {};
  for (var i = 0; i < arr.length; i++) {
    var p = arr[i][key];
    if (!split[p]) {
      split[p] = [];
    }
    split[p].push(arr[i])
  }
  return Object.values(split);
}


var buckets2 = splitArrayByValue(filter, 'arrayPicklist');

console.log(buckets2);

You can use the function reduce to group and then the function Object.values to get the desired output.

var filter = [{"Id":"120","arrayPicklist":"Categorie__c"},{"Id":"121","arrayPicklist":"Regio__c"},{"Id":"122","arrayPicklist":"Categorie__c"},{"Id":"123","arrayPicklist":"Regio__c"},{"Id":"121","arrayPicklist":"Regio__c"}];

var result = Object.values(filter.reduce((a, {Id, arrayPicklist}) => {
  (a[arrayPicklist] || (a[arrayPicklist] = [])).push({Id, arrayPicklist});      
  return a;
}, {}));

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

Just return Object.values(split) instead of split in splitArrayByValue function.

var filter = [{"Id":"120","arrayPicklist":
"Categorie__c"},{"Id":"121","arrayPicklist":"Regio__c"},
{"Id":"122","arrayPicklist":"Categorie__c"},{"Id":"123","arrayPicklist":"Regio__c"},
{"Id":"121","arrayPicklist":"Regio__c"}]


function splitArrayByValue(arr, key) {
  var split = {};
  for (var i=0; i<arr.length; i++) {
    var p = arr[i][key];
    if (!split[p]) { split[p] = []; }
    split[p].push(arr[i])
  }
  return Object.values(split);//<---- just return Object.values(split) instead of split 
}


var buckets2 = splitArrayByValue(filter,'arrayPicklist');

console.log(buckets2);

You can use .reduce():

let data = [
  {"Id":"120", "arrayPicklist":"Categorie__c"},
  {"Id":"121", "arrayPicklist":"Regio__c"},
  {"Id":"122", "arrayPicklist":"Categorie__c"},
  {"Id":"123", "arrayPicklist":"Regio__c"},
  {"Id":"121", "arrayPicklist":"Regio__c"}
];

let keys = [...new Set(data.map(({arrayPicklist}) => arrayPicklist))];

/* 
 * let keys = ["Categorie__c", "Regio__c"];
 * In case you wants to use hard code values
 */

let result = data.reduce((r, c) => (
    r[keys.indexOf(c["arrayPicklist"])].push(c), r
), [[], []]);

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

Useful Resources:

  • Array.prototype.reduce()
  • Arrow Functions
  • Comma Operator

Make a set of all possible categories (arrayPicklist). For each value in this set, filter the array and create a group:

var array = [
    {"Id": "120", "arrayPicklist": "Categorie__c"},
    {"Id": "121", "arrayPicklist": "Regio__c"},
    {"Id": "122", "arrayPicklist": "Categorie__c"},
    {"Id": "123", "arrayPicklist": "Regio__c"},
    {"Id": "121", "arrayPicklist": "Regio__c"}
]

let groups = [...new Set(array.map(x => x.arrayPicklist))]
    .map(p => array.filter(x => x.arrayPicklist === p));

console.log(groups)

That said, you should really consider using a library. Well-designed and well-tested tools are always preferred to any fragile ad-hoc bination of javascript built-ins one can e up with. With lodash, your problem is solved in one line:

let groups = _.values(_.groupBy(array, 'arrayPicklist'))

as it is with Ramda:

let groups  = R.values(R.groupBy(x => x.arrayPicklist, array))

If I understand correctly, you want to get the values of the object as an array instead. You can acheive this using the following methods:

1. Object.values:

When you return from splitArrayByValue, return this:

return Object.values(split);

instead of:

return split;

Object.values works only in ECMAScript 2017. If your have the older ECMA, then use the second method, which acheives the same

2. Object.keys & Array#map:

As above, instead of returning split directly, return this:

return Object.keys(split).map(function(key) {
  return split[key];
});

or shorter using an arrow function:

return Object.keys(split).map(key => split[key]);

Note: In both the above methods, the order of the subarrays is not specified. It could be anything. It could be [[Regio__c], [Categorie__c]] as it could be [[Categorie__c], [Regio__c]] as object in javascript don't preserve the order of their key-value pairs.

I understand that you want to end up with a 2D array with the first level representing the arrayPicklist value. If that is correct, you could use map and Set to achieve what you want e.g.

var filter = [{"Id":"120","arrayPicklist":
"Categorie__c"},{"Id":"121","arrayPicklist":"Regio__c"},
{"Id":"122","arrayPicklist":"Categorie__c"},{"Id":"123","arrayPicklist":"Regio__c"},
{"Id":"121","arrayPicklist":"Regio__c"}]


function splitArrayByValue(arr, key) {
  let keys = arr.map(entry => {
    return entry[key];
  });

  let unique = [...new Set(keys.concat())]; 

  let split = new Array(unique.length);
  for (var i = 0; i < arr.length; i++) {
    let p = arr[i][key];
    let index = unique.indexOf(p);

    if (!split[index]) split[index] = [];
    split[index].push(arr[i])
  }
  return split;
}


var buckets2 = splitArrayByValue(filter,'Id');

console.log(buckets2);
发布评论

评论列表(0)

  1. 暂无评论