Andrews
Andrews

Reputation: 43

How to get the values of an array of an array of objects

So I have an array like this. Like array containing an array of objects.

posts = [
  [
    {
      "id": 2,
      "info": "This is some information"
    },
    {
      "id": 3,
      "info": "This is the other information"
    }
  ],
  [
    {
      "id": 2,
      "info": "This is a duplicated id I want to remove"
    },
    {
      "id": 4,
      "info": "This information is safe"
    }
  ]
]

I want to get the elements from each array and create a new array that only has the objects at the same time removing duplicated ids. What am trying to achieve is something like

posts = [
   {
      "id": 2,
      "info": "This is some information"
    },
    {
      "id": 3,
      "info": "This is the other information"
    },
      {
      "id": 4,
      "info": "This information is safe"
    }
]

This is the code I have so far

id = ids.map(val => {
  for(let i in val) {
    console.log(val)
  }
return something
})

I keep getting undefined values. I have tried forEach, for loop. Any help would be much appreciated. Thanks

Upvotes: 0

Views: 45

Answers (5)

mstephen19
mstephen19

Reputation: 1926

You could use .flat() and then .filter():

const posts = [
    [
        {
            id: 2,
            info: 'This is some information',
        },
        {
            id: 3,
            info: 'This is the other information',
        },
    ],
    [
        {
            id: 2,
            info: 'This is a duplicated id I want to remove',
        },
        {
            id: 4,
            info: 'This information is safe',
        },
    ],
];

const newPosts = posts.flat().filter((x, i, self) => i === self.findIndex((y) => x.id === y.id));

console.log(newPosts);

Another potential (and more optimal) solution could be this using .reduce():

const posts = [
    [
        {
            id: 2,
            info: 'This is some information',
        },
        {
            id: 3,
            info: 'This is the other information',
        },
    ],
    [
        {
            id: 2,
            info: 'This is a duplicated id I want to remove',
        },
        {
            id: 4,
            info: 'This information is safe',
        },
    ],
];

const newPosts = Object.values(posts.flat().reduce((acc, curr) => {
    return {
        ...acc,
        ...(!acc[curr.id] ? { [curr.id]: curr } : undefined),
    };
}, {}));

console.log(newPosts);

Or, if you don't like .reduce(), you can do something very similar with the Map object and a for...of loop:

const posts = [
    [
        {
            id: 2,
            info: 'This is some information',
        },
        {
            id: 3,
            info: 'This is the other information',
        },
    ],
    [
        {
            id: 2,
            info: 'This is a duplicated id I want to remove',
        },
        {
            id: 4,
            info: 'This information is safe',
        },
    ],
];

const map = new Map();

for (const item of posts.flat()) {
    if (map.has(item.id)) continue;

    map.set(item.id, item);
}

const newPosts = Array.from(map.values());

console.log(newPosts);

Or even use a classic for loop to get the job done:

const posts = [
    [
        {
            id: 2,
            info: 'This is some information',
        },
        {
            id: 3,
            info: 'This is the other information',
        },
    ],
    [
        {
            id: 2,
            info: 'This is a duplicated id I want to remove',
        },
        {
            id: 4,
            info: 'This information is safe',
        },
    ],
];

const flattened = posts.flat();
const map = {};

for (let i = 0; i < flattened.length; i++) {
    if (map[flattened[i].id]) continue;

    map[flattened[i].id] = flattened[i];
}

console.log(Object.values(map));

Either way, in each of these examples we're following the same workflow:

  1. Flatten the array so that all items are on the same level.
  2. Filter out the items with the duplicate IDs.

Upvotes: 1

Brother58697
Brother58697

Reputation: 3178

There are two things we need to do:

  • Flatten the inner areas into one main array with array.prototype.flat()
  • Remove duplicates based on, I'm assuming, the order of their appearance in the data.
    • We can do this by reducing the flattened array to an object with a condition that doesn't add any present id's if they're found
    • Then we convert that object to an array using Object.values()

let posts = [ [ { "id": 2, "info": "This is some information" }, { "id": 3, "info": "This is the other information" } ], [ { "id": 2, "info": "This is a duplicated id I want to remove" }, { "id": 4, "info": "This information is safe" } ] ]

let flattened = posts.flat()
console.log('Flattened: ', flattened)

let unique = flattened.reduce((acc, obj) => {
  if (!acc[obj.id]) {
    acc[obj.id] = obj
  }
  return acc
}, {})
console.log('Unique Objects: ', unique)

let result = Object.values(unique)
console.log('Final Array: ' ,result)

Doing it in one go and with a spread ... object merge:

let posts = [ [ { "id": 2, "info": "This is some information" }, { "id": 3, "info": "This is the other information" } ], [ { "id": 2, "info": "This is a duplicated id I want to remove" }, { "id": 4, "info": "This information is safe" } ] ]

let result = Object.values(
  posts.flat().reduce((acc, obj) => 
    ({...{[obj.id]: obj}, ...acc})
  , {})
);
console.log('Final Array: ', result);

Upvotes: 0

Andy
Andy

Reputation: 63589

Use flat to get a flattened array of objects, and then loop over the array. If the current object's id can't be found in an object in the output array push that object.

const posts=[[{id:2,info:"This is some information"},{id:3,info:"This is the other information"}],[{id:2,info:"This is a duplicated id I want to remove"},{id:4,info:"This information is safe"}]];

const out = [];

for (const obj of posts.flat()) {
  const found = out.find(f => obj.id === f.id);
  if (!found) out.push(obj);
}

console.log(out);

Upvotes: 1

tenshi
tenshi

Reputation: 26404

Flatten the array with flat, then use a set to keep track of the ids we already have. The ternary inside the filter is logic to check if the id is already in the set, and if it is, we filter the item out. Otherwise, we add the id back to the set.

const posts = [[{id:2,info:"This is some information"},{id:3,info:"This is the other information"}],[{id:2,info:"This is a duplicated id I want to remove"},{id:4,info:"This information is safe"}]];

const flat = posts.flat();

const ids = new Set();

const filtered = flat.filter((item) => ids.has(item.id) ? false : ids.add(item.id));

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

Upvotes: 0

IT goldman
IT goldman

Reputation: 19511

I group by id in order to remove duplicates.

var posts = [[{id:2,info:"This is some information"},{id:3,info:"This is the other information"}],[{id:2,info:"This is a duplicated id I want to remove"},{id:4,info:"This information is safe"}]];

var agg = {}
posts.forEach(function(arr) {
  arr.forEach(function(item) {
    agg[item.id] = agg[item.id] || item
  })
})

console.log(Object.values(agg))
.as-console-wrapper {
  max-height: 100% !important
}

Upvotes: 0

Related Questions