Ujjawal Raj
Ujjawal Raj

Reputation: 150

how to create a list of list of objects from a list of objects?

So, I am trying to create a list of list of objects using some existing data. The data i have contains 2 values i.e. 'a' and 'b' with many similar values of 'a' recurring many times in the dataset.

What i am trying to do is to convert the data in such a format that for any value of 'a', the list would contain all the value of 'b' corresponding to its 'a' value in a single place.

The Dataset is :

const tempData = [
{a: 1557637200025, b: "aaaa"},
{a: 1557637200025, b: "bbbb"},
{a: 1557637200025, b: "cccc"},
{a: 1557637200025, b: "dddd"},
{a: 1557637200025, b: "eeee"},
{a: 1557637200025, b: "ffff"},
{a: 1557637200025, b: "gggg"},
{a: 1555563600017, b: "hhhh"},
{a: 1555563600017, b: "iiii"},
{a: 1555563600017, b: "jjjj"},
{a: 1555563600017, b: "kkkk"},
{a: 1555563600017, b: "llll"},
{a: 1555563600017, b: "mmmm"},
{a: 1555563600017, b: "nnnn"},
{a: 1555563600017, b: "oooo"},
{a: 1555563600017, b: "pppp"},
{a: 1555563600017, b: "qqqq"},
{a: 1555563600017, b: "rrrr"},
{a: 1555563600017, b: "ssss"},
{a: 1555563600017, b: "tttt"},
{a: 1555563600017, b: "uuuu"},
{a: 1557982800028, b: "vvvv"},
]

And i want it to look like this:

const newTempData = [
{
 a: 1557637200025,b: [
    "aaaa",
    "bbbb",
    ...
]},
{
 a: 1555563600017,b: [
    "hhhh",
    "iiii",
]},
...

]

I have tried basic nested for loops and i am getting no where close to achieve what i am seeking.I am not getting any way to update the row1 value inside for loop for row2, so that i can stop the loop to match the values again and again.

        var newTempData =[];
        for(let row1 in tempData){
            console.log(row1);
            var some =[];
            var row2 = Number(row1)+1;
            var x = tempData[row1].a;
            for(row2 in tempData) {
                var y = tempData[row2].a;
                var instance = tempData[row2].b;
                if( x === y ){
                    some.push({ ins : instance});
                }
            }
            newTempData.push({a: x,b: some});
        }

        console.log(newTempData);

The output i am getting is this.

0: {a: 1557637200025, b: Array(7)}
1: {a: 1557637200025, b: Array(7)}
2: {a: 1557637200025, b: Array(7)}
3: {a: 1557637200025, b: Array(7)}
4: {a: 1557637200025, b: Array(7)}
5: {a: 1557637200025, b: Array(7)}
6: {a: 1557637200025, b: Array(7)}
7: {a: 1555563600017, b: Array(14)}
8: {a: 1555563600017, b: Array(14)}
9: {a: 1555563600017, b: Array(14)}
10: {a: 1555563600017, b: Array(14)}
11: {a: 1555563600017, b: Array(14)}
12: {a: 1555563600017, b: Array(14)}
13: {a: 1555563600017, b: Array(14)}
14: {a: 1555563600017, b: Array(14)}
15: {a: 1555563600017, b: Array(14)}
16: {a: 1555563600017, b: Array(14)}
17: {a: 1555563600017, b: Array(14)}
18: {a: 1555563600017, b: Array(14)}
19: {a: 1555563600017, b: Array(14)}
20: {a: 1555563600017, b: Array(14)}
21: {a: 1557982800028, b: Array(1)}

I just want to get the desired data without repetition. Right now i am able to get the data but it is repeating for every matched value of 'a'. I want to know better ways to do it rather than my amateur way. Thanks.

Upvotes: 2

Views: 100

Answers (3)

Ricola
Ricola

Reputation: 2932

If you care about performance, instead of using .find() of your array, you could use a Map :

  function add(map, {a,b}) {
    if (!map.has(a)) {
      map.set(a, {a:a, b:[]});
    }
    map.get(a).b.push(b);
    return map;
  }

  const result = Array.from(tempData.reduce(add, new Map()).values());

EDIT: or even better, use an object as in @Vishal Sharma's answer, has less overhead than a map.

Upvotes: 2

Vishal Sharma
Vishal Sharma

Reputation: 2610

Instead of running .find each time you could create an object {} as part of reduce, to avoid the effort of finding the element each time, and later use Object.values

const result = Object.values(tempData.reduce((acc, {a, b}) => {
    if (acc[a]) {
        acc[a].b.push(b)
    } else {
        acc[a] = {a, b: [b]}
    }

    return acc
}, {}))

Upvotes: 1

Alvaro
Alvaro

Reputation: 9682

Try with reduce. I have commented out the check if b is already in the array, depends if you want repeated b values or not.

const tempData = [
    { a: 1557637200025, b: "aaaa" },
    { a: 1557637200025, b: "bbbb" },
    { a: 1557637200025, b: "cccc" },
    { a: 1557637200025, b: "dddd" },
    { a: 1557637200025, b: "eeee" },
    { a: 1557637200025, b: "ffff" },
    { a: 1557637200025, b: "gggg" },
    { a: 1555563600017, b: "hhhh" },
    { a: 1555563600017, b: "iiii" },
    { a: 1555563600017, b: "jjjj" },
    { a: 1555563600017, b: "kkkk" },
    { a: 1555563600017, b: "llll" },
    { a: 1555563600017, b: "mmmm" },
    { a: 1555563600017, b: "nnnn" },
    { a: 1555563600017, b: "oooo" },
    { a: 1555563600017, b: "pppp" },
    { a: 1555563600017, b: "qqqq" },
    { a: 1555563600017, b: "rrrr" },
    { a: 1555563600017, b: "ssss" },
    { a: 1555563600017, b: "tttt" },
    { a: 1555563600017, b: "uuuu" },
    { a: 1557982800028, b: "vvvv" }
];

const result = tempData.reduce((acc, { a, b }) => {
    const element = acc.find(el => el.a === a);

    // If element exists
    if (element /* && !element.b.includes(b) */) {
        element.b.push(b);

        return acc;
    }/* else if ( element ) { return acc; } */

    acc.push({ a, b: [b] });

    return acc;
}, []);

Upvotes: 4

Related Questions