1

I am trying to use underscore to group my array of objects in a smaller list:

    var list = [
  { Region: 'A', Vals: [ 7, 'H' ] },
  { Region: 'B', Vals: [ 40, 'H' ] },
  { Region: 'B', Vals: [ 24, 'VH' ] },
  { Region: 'C', Vals: [ 4, 'VH' ] },
  { Region: 'A',Vals: [ 40, 'VH' ] }
  ];


    var groups = _.groupBy(list, function(value){
        return value.Region;
    });

var grouped = _.map(groups, function(group){
        return {
            Region: group[0].Region,
            Vals: group[0].Vals
        }
    });

Which will get somewhat close, but it is missing some of the Vals. I want the arrays of 'vals' concatenated based on keys.

   var list = [
  { Region: 'A', Vals: [ 7, 'H', 40, 'VH' ] },
  { Region: 'B', Vals: [ 40, 'H',  24, 'VH' ] },
  { Region: 'B', Vals: [ 24, 'VH' ] },
  { Region: 'C', Vals: [ 4, 'VH' ] }
  ];

http://jsfiddle.net/77gL11c9/1/

2
  • You can get all the Vals by replacing the group[0].Vals with _.flatten(_.pluck(group, 'Vals')) Commented Jan 9, 2017 at 19:28
  • var res = list.reduce(function(arr, v) { if (!(v.Region in ref)) { ref[v.Region] = arr.length; arr.push({Region: v.Region, Vals: v.Vals}); } else{ [].push.apply(arr[ref[v.Region]].Vals, v.Vals); } return arr; }, []); Commented Jan 10, 2017 at 4:09

3 Answers 3

2
list.reduce(function (memo, v) {
  if (memo[v.Region]) {
    memo[v.Region] = memo[v.Region].concat(v.Vals)
  } else {
    memo[v.Region] = v.Vals.slice()
  }
  return memo
}, {})

The output will look like this:

{
  A: [ 7, "H", 40, "VH" ],
  B: [40, "H", 24, "VH" ],
  C: [ 4, "VH" ]
}
Sign up to request clarification or add additional context in comments.

Comments

1

Use native JavaScript Array#reduce method with a reference object to hold the index.

var list = [
  { Region: 'A', Vals: [ 7, 'H' ] },
  { Region: 'B', Vals: [ 40, 'H' ] },
  { Region: 'B', Vals: [ 24, 'VH' ] },
  { Region: 'C', Vals: [ 4, 'VH' ] },
  { Region: 'A',Vals: [ 40, 'VH' ] }
];


// object for refering index
var ref = {};

// iterate over the array
var res = list.reduce(function(arr, v) {
      // check property defined if not define and push
      // value to array
      if (!(v.Region in ref)) {
        ref[v.Region] = arr.length;
        arr.push({Region: v.Region, Vals: v.Vals});
      // if index already defined then push values
      } else{
        [].push.apply(arr[ref[v.Region]].Vals, v.Vals);
      }
    // return the array reference
    return arr;
  // set initial value as empty array
}, []);

console.log(res);


UPDATE : If you want to generate an object where Region value as property name and Vals value as it's value then do something like this.

var list = [
  { Region: 'A', Vals: [ 7, 'H' ] },
  { Region: 'B', Vals: [ 40, 'H' ] },
  { Region: 'B', Vals: [ 24, 'VH' ] },
  { Region: 'C', Vals: [ 4, 'VH' ] },
  { Region: 'A',Vals: [ 40, 'VH' ] }
];


// iterate over the array
var res = list.reduce(function(obj, v) {
  // define the property as an array if not 
  // already defined
  obj[v.Region] = obj[v.Region] || [];
  
  // push all values to array
  [].push.apply(obj[v.Region], v.Vals);
  
  // return the object reference
  return obj;
  
  // set initial value as an empty object
}, {});

console.log(res);

Comments

0

This will produce the exact output that you are looking for.

//first build an object with Region properties, and add the Vals to each of those properties

var tempList = {}; 
for (var i=0; i < list.length; i++) {
  if (!(list[i].Region in tempList)) {
    tempList[list[i].Region] = [];
  }
  Array.prototype.push.apply(tempList[list[i].Region],list[i].Vals);
}

//then format this as an array of objects    
var groupedList = [];
for (var region in tempList) {
    groupedList.push({Region:region, Vals: tempList[region]});
}

list = groupedList;

After the above code, the following will be true:

list = [
  { Region: 'A', Vals: [ 7, 'H', 40, 'VH' ] },
  { Region: 'B', Vals: [ 40, 'H',  24, 'VH' ] },
  { Region: 'B', Vals: [ 24, 'VH' ] },
  { Region: 'C', Vals: [ 4, 'VH' ] }
];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.