0

I am having an array of objects and I want to create another object based on their keys. For example I am having an array as

var arr = [{1: 36011, 2: 18320, 3: 36011, 4: 10570},
            {1: 19754, 2: 6722, 3: 19754, 4: 6699},
            {1: 15711, 2: 10039, 3: 15711, 4: 4172}]

and I want my result array as

var result = {1:[36011,19754,15711], 2:[18320,6722,10039],..}

I was suggested to use lodash, I am new to this so I've tried using reduce

var i = 1, new_arr = {};
_.reduce(arr, function(key, val){
     new_arr[i++] = temp1.key 
return new_arr;
},{})

I am getting the values as undefined. What is the mistake, Can anyone help me with this?

image

Community
  • 1
  • 1
Lahari
  • 461
  • 1
  • 3
  • 16
  • There is no need for lodash, reduce is widely supported. This is almost 2020! The `i` in your code is global, so it will count all the values. The reduce in your code cannot have key/val pair since you are applying it to an array. – kornieff Dec 01 '19 at 04:58
  • Neither of the questions indicated in "close as duplicate" had answers to this question. Both of those were about grouping on a single, specific property, whereas this is about cross-merging multiple objects on arbitrary properties. – JLRishe Dec 01 '19 at 07:08

4 Answers4

2

This might look intimidating at first. Start reducing the dataset from an empty object. Then reduce each row starting with result of outer reduce and build on the result so far.

const addToBucket = (bucket = {}, k, v, prev = bucket[k] || []) => ({
  ...bucket,
  [k]: [...prev, v],
})

const toBucket = list =>
  list.reduce(
    (bucket, row) =>
      Object.entries(row).reduce((b, [k, v]) => addToBucket(b, k, v), bucket),
    {},
  )

const data = [
  { 1: 36011, 2: 18320, 3: 36011, 4: 10570 },
  { 1: 19754, 2: 6722, 3: 19754, 4: 6699 },
  { 1: 15711, 2: 10039, 3: 15711, 4: 4172 },
]

console.log(toBucket(data))

// Nested list, as requested
console.log(Object.entries(toBucket(data)).map(([_, v]) => v))
kornieff
  • 2,389
  • 19
  • 29
2

with lodash you can use _.mergeWith() and concat the values in the customiser function:

const arr = [{"1":36011,"2":18320,"3":36011,"4":10570},{"1":19754,"2":6722,"3":19754,"4":6699},{"1":15711,"2":10039,"3":15711,"4":4172}]
            
const result = _.mergeWith({}, ...arr, (ov = [], sv) => ov.concat(sv))

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
0

You can try like this in simplest way.

This is also available online at https://rextester.com/IPI35964 to try and see output.

var arr = [{1: 36011, 2: 18320, 3: 36011, 4: 10570},
        {1: 19754, 2: 6722, 3: 19754, 4: 6699},
        {1: 15711, 2: 10039, 3: 15711, 4: 4172}]

var output = {}
for(var obj of arr){
    for(var key in obj){
        if(key in output){
            output[key].push(obj[key])
        } else {
            output [key] = [obj[key]]
        }
    }
}
console.log(output)

Output

{ '1': [ 36011, 19754, 15711 ],
  '2': [ 18320, 6722, 10039 ],
  '3': [ 36011, 19754, 15711 ],
  '4': [ 10570, 6699, 4172 ] }
hygull
  • 8,464
  • 2
  • 43
  • 52
0

One fairly clean way of doing this:

  • Create one big array of key-value pairs
  • Group those key-value pairs by their keys
  • Extract the values from the grouped key-value pairs

var arr = [
  { 1: 36011, 2: 18320, 3: 36011, 4: 10570 },
  { 1: 19754, 2: 6722, 3: 19754, 4: 6699 },
  { 1: 15711, 2: 10039, 3: 15711, 4: 4172 }
];

// Get one big array of all key-value pairs
var pairs = _.flatMap(arr, _.entries);

// Group by the keys (index 0 of the pairs)
var groups = _.groupBy(pairs, 0);

// Extract the values
var final = _.mapValues(groups, _.partial(_.map, _, 1));

//console.log(pairs);
console.log(final);


// Using chaining:
var final2 = _.chain(arr)
  .flatMap(_.entries)
  .groupBy(0)
  .mapValues(_.partial(_.map, _, 1));

console.log(final2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
JLRishe
  • 99,490
  • 19
  • 131
  • 169