2

I have an array of objects that I want to transform. My dataset looks like this:

[
 {
  day: sunday,
  val: 20
 }, 
{
  day: sunday,
  val: 20
 }, 
{
  day: monday,
  val: 10
 },  
{
  day: monday,
  val: 30
 }, 
{
  day: tuesday,
  val: 5
 }, 
{
  day: tuesday,
  val: 5
 }
]

I am trying to transform the data to look like this:

Output: [[20,20], [10,30], [5, 5]]

Where each of the nested arrays are based on the Day of Week in object. Any ideas?

Thanks!

Pat Doyle
  • 384
  • 2
  • 5
  • 16
  • Is the dataset guaranteed to be ordered by day of the week (sunday, monday, tueday, etc.)? In other words, can it be (tuesday, monday, friday, tuesday)? – Brandon Tiqui Sep 12 '20 at 00:08

5 Answers5

1

You could group your items by their day. After you have the groups, you can grab the values of the map and map the item lists to a list of val.

const data = [
  { day: 'sunday'  , val: 20 }, { day: 'sunday'  , val: 20 },
  { day: 'monday'  , val: 10 }, { day: 'monday'  , val: 30 },
  { day: 'tuesday' , val:  5 }, { day: 'tuesday' , val:  5 }
];

const transformed = Object.values(data.reduce((map, item) =>
  ({ ...map, [item.day] : [ ...(map[item.day] || []), item]
}), {})).map(list => list.map(item => item.val));

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

Alternatively, you can reduce the values right away, but you lose all the item properties.

const data = [
  { day: 'sunday'  , val: 20 }, { day: 'sunday'  , val: 20 },
  { day: 'monday'  , val: 10 }, { day: 'monday'  , val: 30 },
  { day: 'tuesday' , val:  5 }, { day: 'tuesday' , val:  5 }
];

const transformed = Object.values(data.reduce((map, item) =>
  ({ ...map, [item.day] : [ ...(map[item.day] || []), item.val] }), {}));

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

Here is a functional version:

const data = [
  { day: 'sunday'  , val: 20 }, { day: 'sunday'  , val: 20 },
  { day: 'monday'  , val: 10 }, { day: 'monday'  , val: 30 },
  { day: 'tuesday' , val:  5 }, { day: 'tuesday' , val:  5 }
];

const toMatrix = (list, key, valFn) => Object.values(data.reduce((map, item) =>
  ({ ...map, [item[key]] : [ ...(map[item[key]] || []), valFn(item) ] }), {}))

console.log(toMatrix(data, 'day', item => item.val));
.as-console-wrapper { top: 0; max-height: 100% !important; }
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • This is exactly what I was looking for. I was struggling to find a way to use reduce to get the desired array. Thank you so much!!! – Pat Doyle Sep 12 '20 at 00:51
0
let myarray=[
 {
  day: 'sunday',
  val: 20
 }, 
{
  day: 'sunday',
  val: 20
 }, 
{
  day: 'monday',
  val: 10
 },  
{
  day: 'monday',
  val: 30
 }, 
{
  day: 'tuesday',
  val: 5
 }, 
{
  day: 'tuesday',
  val: 5
 }
];

let newarray=[];

for (let x of myarray) {
    if (!newarray[x.day]) { newarray[x.day]=[]; }
    newarray[x.day].push(x.val);
}

console.log(newarray);
0

Here is an example on stackblitz on how you could achieve that, and here is the code :

import React, { Component } from "react";
import { render } from "react-dom";
import * as _ from "lodash";

const App = () => {
  const data = [
    {
      day: "sunday",
      val: 20
    },
    {
      day: "sunday",
      val: 20
    },
    {
      day: "monday",
      val: 10
    },
    {
      day: "monday",
      val: 30
    },
    {
      day: "tuesday",
      val: 5
    },
    {
      day: "tuesday",
      val: 5
    }
  ];

  const groupBy = (arr, prop) => {
    const map = new Map(Array.from(arr, obj => [obj[prop], []]));
    arr.forEach(obj => map.get(obj[prop]).push(obj.val));
    return Array.from(map.values());
  };

  React.useEffect(() => {
    // groupBy from Lodash does not do exaclty what you want (but still very interesting), need to work on it a bit
    let chunks = Object.values(_.groupBy(data, 'day')).map(x => x.map(item => item.val));
    console.log(chunks);

    // Exactly what you want, but custom made by someone here :
    // https://stackoverflow.com/a/53704154/9868549
    console.log(groupBy(data, 'day'));
  }, []);

  return <div>This is a template react</div>;
};

render(<App />, document.getElementById("root"));

I found it here on another StackOverflow thread but still wanted to provide another solution with lodash.

Quentin Grisel
  • 4,794
  • 1
  • 10
  • 15
0

This could be a solution:

var obj = [
 {
  day: 'sunday',
  val: 20
 }, 
{
  day: 'sunday',
  val: 20
 }, 
{
  day: 'monday',
  val: 10
 },  
{
  day: 'monday',
  val: 30
 }, 
{
  day: 'tuesday',
  val: 5
 }, 
{
  day: 'tuesday',
  val: 5
 }
]

var obj_output = [];
var bln_array = false;

for (i=0; i < obj.length; i++) {
  var arr = [];
    arr.push(obj[i].val);
  arr.push(obj[i+1].val);
  obj_output.push(arr);
  i = i+1
}

console.log(obj_output);
Michele Pisani
  • 13,567
  • 3
  • 25
  • 42
0

Here's one way to achieve this

var old = [
 { day: 'sunday',  val: 20 }, 
 { day: 'sunday',  val: 20 }, 
 { day: 'monday',  val: 10 },  
 { day: 'monday',  val: 30 }, 
 { day: 'tuesday', val:  5 }, 
 { day: 'tuesday', val:  5 }
];

var days = []; 
var result = [];
old.forEach(o => {
  if(days.indexOf(o.day) === -1) {
    days.push(o.day);
    result.push([]);
  }
  result[days.indexOf(o.day)].push(o.val);
});

console.log(result);
Majid Fouladpour
  • 29,356
  • 21
  • 76
  • 127