0

This answer is already close, and there are some answers how to get unique values in an array (remove duplicates,)though I can't make it work for the case where it is about an array of objects, and the property that should be filtered is an array. Sorry, I am a JS newbie. Thanks for the help.

I have an array of objects like this

const posts = [
  post1: {
    id: 1,
    title: 'One',
    tags: ['tagA', 'tagB']
    },
  post2: {
    id: 2,
    title: 'Two',
    tags: ['tagB', 'tagC']    
    },
  post3: {
    id: 3,
    title: 'Three',
    tags: ['tagB', tagC, tagD]    
    ]

What I would need is an array of all unique tags ... in the case above with an expected output like this:

// [tagA, tagB, tagC, tagD] 

EDIT / UPDATE

The key in the array of objects is used to manage the state of the react component... e.g.

constructor(props) {
super(props);

this.state = {
  posts: []
};
}

...

updatePost = (key, updatedPost) => {
//1. Take copy of the current this.state.
const posts = {...this.state.texts};
//2. Update that state
posts[key] = updatedPost;
//3. Set that to state
const options = { encrypt: false }
putFile(postsFileName, JSON.stringify(posts), options)
  .then(() => {
    this.setState({
      posts: posts
    })
  })
  };
4
  • 1
    Your posts are not valid JS, should it be directly object in your array? Commented Jun 26, 2018 at 17:06
  • 1
    This is not a valid array. Commented Jun 26, 2018 at 17:08
  • In case you don't get what they are saying, posts is an array, post1, post2, post3, would be keys in an object, not an array. Did you copy over something incorrectly? Commented Jun 26, 2018 at 17:10
  • Sorry, guys, apologies if I use the wrong terms here. This what I mentioned as "array of objects", is the state that I get in my react component, after adding posts. The key is added to manage / update the posts... see the "edit / update" above. Commented Jun 26, 2018 at 17:24

5 Answers 5

3

Assuming that the input is on [ {} , {} ] format:

You can use concat and map to flatten your array. Use new Set to get the unique values.

const posts = [{"id":1,"title":"One","tags":["tagA","tagB"]},{"id":2,"title":"Two","tags":["tagB","tagC"]},{"id":3,"title":"Three","tags":["tagB","tagC","tagD"]}];

var result = [...new Set([].concat(...posts.map(o => o.tags)))];

console.log(result);


If the variable is an object ( {a:{} , b:{} } ) , you can use Object.values to convert the object into an array.

const posts = {"post1":{"id":1,"title":"One","tags":["tagA","tagB"]},"post2":{"id":2,"title":"Two","tags":["tagB","tagC"]},"post3":{"id":3,"title":"Three","tags":["tagB","tagC","tagD"]}}

var result = [...new Set([].concat(...Object.values(posts).map(o => o.tags)))];

console.log(result);

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

1 Comment

I want to upvote this, but it really depends on if OPs dataset is supposed to be an Object or an Array.
0

You can reduce your posts and iterate over the tags and push those to the result that you haven't encountered already:

const posts = [
  {
    id: 1,
    title: "One",
    tags: ["tagA", "tagB"]
  },
  {
    id: 2,
    title: "Two",
    tags: ["tagB", "tagC"]
  },
  {
    id: 3,
    title: "Three",
    tags: ["tagB", "tagC", "tagD"]
  }
];

const uniqueTags = posts.reduce((result, post) => {
  post.tags.forEach(tag => {
    if (!result.includes(tag)) {
      result.push(tag);
    }
  });

  return result;
}, []);

console.log(uniqueTags);

Comments

0

This is assuming you know that the array key is always 'tags'.

let filter = {};
let result = [];

posts.forEach(post => {
  const tags = post['tags'];
  tags.forEach(tag => {
    if (!filter.hasOwnProperty(tag)) {
      result.push(tag);
      filter[tag] = true; 
    }
  });
});

Comments

0

with jquery you can do something similar to this (not Tested):

var results = [];
$.each(myObject, function(key,valueObj){
    var check.isArray(obj);
    if(check){
        alert(key + "/" + valueObj );
        /*replace repeat*/
        var sorted_check = check.slice().sort(); // You can define the comparing function here. 
                                     // JS by default uses a crappy string compare.
                                     // (we use slice to clone the array so the
                                     // original array won't be modified)

        for (var i = 0; i < sorted_check.length - 1; i++) {
            if (sorted_check[i + 1] == sorted_check[i]) {
                results.push(sorted_check[i]);
            }
        }
    }
});

and a good way with indexof:

Array.prototype.unique = function() {
    var a = [];
    for ( i = 0; i < this.length; i++ ) {
        var current = this[i];
        if (a.indexOf(current) < 0) a.push(current);
    }

    this.length = 0;
    for ( i = 0; i < a.length; i++ ) {
        this.push( a[i] );
    }

    return this;
}

Array.prototype.unique = function() {
    var a = [];
    for ( i = 0; i < this.length; i++ ) {
        var current = this[i];
        if (a.indexOf(current) < 0) a.push(current);
    }
    return a;
}

And Follow UP:

Array.prototype.unique = function(mutate) {
    var unique = this.reduce(function(accum, current) {
        if (accum.indexOf(current) < 0) {
            accum.push(current);
        }
        return accum;
    }, []);
    if (mutate) {
        this.length = 0;
        for (let i = 0; i < unique.length; ++i) {
            this.push(unique[i]);
        }
        return this;
    }
    return unique;
}

Comments

0

If you want to use a functional library like Ramda.js you can do this:

const posts = [
	{
		id: 1,
		title: 'One',
		tags: ['tagA', 'tagB'],
	},
	{
		id: 2,
		title: 'Two',
		tags: ['tagB', 'tagC'],
	},
	{
		id: 3,
		title: 'Three',
		tags: ['tagB', 'tagC', 'tagD'],
	},
];

var unique = R.uniq(R.flatten(R.map(R.prop('tags'), posts)))
console.log(unique)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

Comments

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.