0

I need some help figuring out how to get unique values from an array of objects in this format. I have reviewed several examples but none had the values of a key being an array. Thanks in advance for your advice.

I have a JS array with complex objects with some object values being arrays:

let array = [
    { key1: ["one","two","four"], key2: [1,2,4] },
    { key1: ["two","four","six"], key2: [2,4,6] },
    { key1: "nine", key2: 9 },
];

I want to get the unique values for all keys in the object (so it will support any structure) and output like this:

[
{
key1: ["one","two","four", "six", "nine"],
key2: [1,2,4,6,9]
}
]
3
  • Why return an array of objects with one object per key? Why not return just a single object? {key1: ["one',"two","four","six","nine"], Key2: [1,2,3,6,9]} Also, it bothers me that the case of key1 and Key1 is different in your question. Commented Jul 20, 2022 at 14:06
  • i will clean up the example Commented Jul 20, 2022 at 14:10
  • Your right I wanted the format you suggested. Commented Jul 20, 2022 at 22:46

3 Answers 3

1

You can try this :

let array = [
    { key1: ["one","two","four"], key2: [1,2,4] },
    { key1: ["two","four","six"], key2: [2,4,6] },
    { key1: "nine", key2: 9 },
];

let keys = [...new Set(array.flatMap(d => Object.keys(d)))];

let valuesAsObj = Object.fromEntries(
    keys.map(k => [
        k,
        [... new Set(array.flatMap(d => d[k] ? d[k] : null).filter(v => v != null && v != undefined))] 
    ])
);

let valuesAsArr = keys.map(k => [... new Set(array.flatMap(d => d[k] ? d[k] : null).filter(v => v != null && v != undefined))])

console.log(valuesAsObj);
console.log(valuesAsArr);

Sign up to request clarification or add additional context in comments.

2 Comments

this works . thanks. I like @joacim-norbeck because gave output as object and array. iI did not ask for that
No probleme ;) Note his doesn't works for object output. I just edited mine to provide ou both solution. Have a nice day !
1

I approached it by creating a Set for each unique property and adding all the properties to that set.

let array = [
{ key1: ["one","two","four"], key2: [1,2,4] },
{ key1: ["two","four","six"], key2: [2,4,6] },
{ key1: "nine", key2: 9 },
];

const result = {};
array.forEach(a => {
  for (let key in a) {
    if (!result[key]) result[key] = new Set();
    let v = a[key];
    if (!Array.isArray(v)) v = [v];
    v.forEach(result[key].add, result[key]);
  }
});

   console.log(result );


const overlyComplicatedResult = Object.entries(result).map(([key,val]) => ({[key]: [...val]}));
console.log(overlyComplicatedResult);

I'm personally happy with the results in the intermediate format that they are stored in the result variable, which is just a single object where each property is one of the keys and the value of each property is a Set of all the distinct values.

But, if you really want to transform that into your overly complicated result, where you have an array of objects, each with a single property, and the unique items are stored in an array instead of a Set, then the code is provided above as a final transformation step using Object.entries.

2 Comments

I like this approach. how can I see the output for result? this is not working console.log(result);
I think I know what's causing you trouble...Stack overflow's snippet tool console output formatter just formats the Set as {}. But if you've added a console.log(result) then you can see the result in your browser's developer tools console (e.g.: F12 on Chrome Windows).
0

You could try something like this:

    let array = [
        { key1: ["one","two","four"], key2: [1,2,4] },
        { key1: ["two","four","six"], key2: [2,4,6] },
        { key1: "nine", key2: 9 },
    ];

        let obj = {};
        array.forEach((item) =>
          Object.entries(item).forEach((entry) => {
            if (!obj[entry[0]]) obj[entry[0]] = [];
            !Array.isArray(entry[1])
              ? obj[entry[0]].push(entry[1])
              : (obj[entry[0]] = [...obj[entry[0]], ...entry[1]]);
          })
        );
        
    /*ADDED LOGIC TO HAVE UNIQUE VALUES IN THE OBJECT*/
    Object.entries(obj).forEach(
      (entry) => (obj[entry[0]] = Array.from(new Set(entry[1])))
    );
        console.log(obj);

        let result = [];
        Object.entries(obj).forEach((entry) =>
          result.push({
            [entry[0]]: Array.from(new Set(entry[1])),
          })
        );

        console.log(result);

3 Comments

The object results are not containing unique values but the array is.
Yeah, that's correct. The log for the object was mostly to see what happened in the first step
I have added logic for getting unique values in the object as well if that is something that you wanted :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.