Pirastrino
Pirastrino

Reputation: 190

How to reduce two depended arrays into an object in JavaScript?

I have two JavaScript arrays of strings as a result from a SQL query (each array is one column in a result) which may contain duplicities like:

arrOne = ["key_1", "key_1", "key_2", "key_3", "key_1", "key_1"]
arrTwo = ["val_1", "val_1", "val_3", "val_3", "val_2", "val_3"]

and I need to reduce them into an object like:

newObj = {
  key_1: ["val_1", "val_2", "val_3"],
  key_2: ["val_3"],
  key_3: ["val_3"]
}

So basically, for each key, value pair, the value should be a reduced list of unique values from an arrTwo.

I have tried:

let newObj = arrOne.reduce((o, k, i) => ({...o, [k]: arrTwo[i]}), {})

which gives me:

{ key_1: 'val_3', key_2: 'val_3', key_3: 'val_3' }

but I need arrTwo[i] part to be reduced list of values instead of last value for each key.

This may have an elegant one-line solution but I am new in JavaScript and I can't find the proper solution (I think a loop is not necessary here).

Upvotes: 3

Views: 140

Answers (3)

brk
brk

Reputation: 50291

Use reduce on one of the first array and use index to access property from second array

var arrOne = ["key_1", "key_1", "key_2", "key_3", "key_1", "key_1"]
var arrTwo = ["val_1", "val_1", "val_3", "val_3", "val_2", "val_3"]

let newObj = arrOne.reduce(function(acc, curr, index) {
  // check if the object has such key and if it dont contain the corresponding value 
  if (acc[curr] && acc[curr].indexOf(arrTwo[index]) === -1) {
    acc[curr].push(arrTwo[index])
  } else {
    acc[curr] = [];
    acc[curr].push(arrTwo[index])

  }

  return acc;
}, {});

console.log(newObj)

Upvotes: 0

Mikhail Vladimirov
Mikhail Vladimirov

Reputation: 13890

const arrOne = ["key_1", "key_1", "key_2", "key_3", "key_1", "key_1"];
const arrTwo = ["val_1", "val_1", "val_3", "val_3", "val_2", "val_3"];
console.log(
  arrTwo.reduce((a, c, i) => {
    if (a[arrOne[i]].indexOf(c) == -1) a[arrOne[i]].push(c);
    return a;
  }, arrOne.reduce((a, c) => {
    a[c] = []; return a;
  }, {})));

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386550

You could take a Set and collect all values.

var arrOne = ["key_1", "key_1", "key_2", "key_3", "key_1", "key_1"],
    arrTwo = ["val_1", "val_1", "val_3", "val_3", "val_2", "val_3"],
    newObj = arrOne.reduce(
        (o, k, i) => ({ ...o, [k]: [...new Set([...(o[k] || []), arrTwo[i]])] }),
        {}
    );

console.log(newObj);

Upvotes: 3

Related Questions