riky1
riky1

Reputation: 98

Javascript get unique value of an indented json

I have JSON array of objects with the following structure:

obj: [
    {   
        itemTitle: 'title-a',
        itemTags: [
            { tag: 'tag-a' },
            { tag: 'tag-b' }
        ]                       
    },
    {   
        itemTitle: 'title-b',
        itemTags: [
            { tag: 'tag-c' }
        ]                       
    },
    {   
        itemTitle: 'title-c',
        itemTags: [
            { tag: 'tag-c' },
            { tag: 'tag-b' }
        ]                       
    }
]

I need to extract distinct tags value in an array like this [tag-a, tag-b, tag-c] I'll try this approach:

const tagsArray = obj.map(elem => elem.itemTags);

var tags = [];
for (var i = 0; i < tagsArray.length; i++) {
    tags.push(tagsArray[i].map(item => item.tag))
}
//tagsArray[0]: [{"tag":"tag-a"},{"tag":"tag-b"}]
//tagsArray[1]: [{"tag":"tag-c"}]
//tagsArray[2]: [{"tag":"tag-c"},{"tag":"tag-b"}]

//tags: tag-a,tag-b,tag-c,tag-c,tag-b

const unique = [...new Set(tags)];
//unique: tag-a,tag-b,tag-c,tag-c,tag-b

it does not return distinct values

Upvotes: 2

Views: 74

Answers (3)

Nguyễn Văn Phong
Nguyễn Văn Phong

Reputation: 14198

Problem

You are pushing the array into each item in tagsArray. The content looks like

[["tag-a","tag-b"],["tag-c"],["tag-c","tag-b"]]

While you need

["tag-a","tag-b","tag-c","tag-c","tag-b"]

Solution

==> Using concat instead of push

const obj = [{itemTitle:'title-a',itemTags:[{tag:'tag-a'},{tag:'tag-b'}]},{itemTitle:'title-b',itemTags:[{tag:'tag-c'}]},{itemTitle:'title-c',itemTags:[{tag:'tag-c'},{tag:'tag-b'}]}];

var tags = [];
const tagsArray = obj.map(elem => elem.itemTags);
for (var i = 0; i < tagsArray.length; i++)
    tags = tags.concat(tagsArray[i].map(item => item.tag)); // Use concat instead of push
const unique = [...new Set(tags)];
console.log(unique);

Refactor code

You can use Array#flatMap

const obj = [{itemTitle:'title-a',itemTags:[{tag:'tag-a'},{tag:'tag-b'}]},{itemTitle:'title-b',itemTags:[{tag:'tag-c'}]},{itemTitle:'title-c',itemTags:[{tag:'tag-c'},{tag:'tag-b'}]}];

const tagsArray = obj.flatMap(({itemTags}) => itemTags.map(({tag}) => tag));
console.log([...new Set(tagsArray )]);

The flatMap() method returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level


Upvotes: 1

Coni Wright
Coni Wright

Reputation: 176

let t=arr.flatMap(item=>item.itemTags.flatMap(tag=>Object.values(tag)))
u = new Set([...t])

Upvotes: 0

Mamun
Mamun

Reputation: 68933

You can try getting the tag in the same loop with flatMap() and map()

var obj = [
    {   
        itemTitle: 'title-a',
        itemTags: [
            { tag: 'tag-a' },
            { tag: 'tag-b' }
        ]                       
    },
    {   
        itemTitle: 'title-b',
        itemTags: [
            { tag: 'tag-c' }
        ]                       
    },
    {   
        itemTitle: 'title-c',
        itemTags: [
            { tag: 'tag-c' },
            { tag: 'tag-b' }
        ]                       
    }
]
const tagsArray = obj.flatMap(elem => elem.itemTags.map(i=>i.tag));

const unique = [...new Set(tagsArray)];
console.log(unique)

Upvotes: 1

Related Questions