0

Hi I'm using reduce to create a more usable JSON structure for the following data.

data = [
  { "0": "key1", "1": "value1" },
  { "0": "key2", "1": "value2" },
  { "0": "key3", "1": "value3" },
  { "0": "key1", "1": "value4" },
];

I used reduce for this, and here is how it looks.

reduce_data = data.reduce((p, c) => {
  p[c["0"]] = c["1"];
  return p;
}, {});
console.log(reduce_data);

Output is as follows

{key1: "value4", key2: "value2", key3: "value3"}

If you see Im missing key1 and its value1. I understand its by design, but Im wondering if there is a way for me to get

{key1: "value1, value4", key2: "value2", key3: "value3"}

Please let me know if I'm using reduce incorrectly. Thanks!

jr0531
  • 25
  • 1
  • 1
  • 3

5 Answers5

0

Theoretically you are doing it right. The problem is that the 4th element also has key1 which overrides the value with value4.


Update

I read the question too fast. A solution could be:

data.reduce(
  (result, { ['0']: key, ['1']: value }) => ({
    ...result, 
    [key]: [result[key], value].filter(Boolean).join(', ')
  }),
  {}
)

Another way (where the result would have the values as an array):

data.reduce(
  (result, { ['0']: key, ['1']: value }) => ({
    ...result, 
    [key]: [...(result[key] || []), value]
  }),
  {}
)
EECOLOR
  • 11,184
  • 3
  • 41
  • 75
0

Check whether the key exists or not and then append rather than assigning (which overrides the value).

Solution here for you...

data.reduce((p, c) => {
  if (p[c["0"]]) {
    p[c["0"]] += ", " + c["1"];
  } else {
    p[c["0"]] = c["1"];
  }

  return p;
}, {});
0

For your specific case you can do it like this:

data = [
  { "0": "key1", "1": "value1" },
  { "0": "key2", "1": "value2" },
  { "0": "key3", "1": "value3" },
  { "0": "key1", "1": "value4" },
];

reduce_data = data.reduce((p, c) => {
  p[c["0"]] = p[c["0"]] ? p[c["0"]] + ", " + c["1"] : c["1"];
  return p;
}, {});
console.log(reduce_data);
Giannis Mp
  • 1,291
  • 6
  • 13
  • The ternary here isn't very readable, but I guess it could be slightly shorter like so: `p[c["0"]] = p[c["0"]] ? p[c["0"]] + ", " + c["1"] : c["1"];` – Salomao Rodrigues Jul 09 '18 at 19:14
  • Thank you! This worked. So now I see my Key has two values, comma separated. I can read this data easily. An additional question I have is, Is there a better way to represent this data? Like `"key1" : {"key1_1": value1, "key1_2" : value2}`. Looking forward to any suggestions! – jr0531 Jul 09 '18 at 19:59
  • I would use an array for each key since there could be multiple values. For example: { "key1": [ "value1", "value4" ], "key2": [ "value2" ], "key3": [ "value3" ]} – Giannis Mp Jul 10 '18 at 07:17
0

You can assign it unless it's already there, in which case concat:

data = [
    { "0": "key1", "1": "value1" },
    { "0": "key2", "1": "value2" },
    { "0": "key3", "1": "value3" },
    { "0": "key1", "1": "value4" },
  ];

  reduce_data = data.reduce((p, c) => {
    p[c["0"]] = (p[c["0"]] || '').concat(", ", c["1"])
    return p;
  }, {});
  console.log(reduce_data);
  

You didn't really ask, but it might be easier to use if you push to an array:

data = [
    { "0": "key1", "1": "value1" },
    { "0": "key2", "1": "value2" },
    { "0": "key3", "1": "value3" },
    { "0": "key1", "1": "value4" },
  ];

  reduce_data = data.reduce((p, c) => {
    (p[c["0"]] || (p[c["0"]] = [])).push(c["1"]);
    return p;
  }, {});
  console.log(reduce_data);
  
Mark
  • 90,562
  • 7
  • 108
  • 148
0

Using ES6 destructirung assignment makes it a bit more clean:

var data = [{ "0": "key1", "1": "value1" }, { "0": "key2", "1": "value2" }, { "0": "key3", "1": "value3" },{ "0": "key1", "1": "value4" },];

var result = data.reduce((p, {"0":key, "1": val}) => {

    if (!p.hasOwnProperty(key)) p[key] = [];
    p[key].push(val);
    return p;

}, {});

console.log(result);
Leonid Pyrlia
  • 1,594
  • 2
  • 11
  • 14