1

I have the following arrays:

const tasks = [
  {id: 0, name: 'a', tags: [{id: 0, name: 'q'}, {id: 1, name: 'w'}]},
  {id: 1, name: 'b', tags: [{id: 2, name: 'e'}, {id: 4, name: 't'}, {id: 11, name: 's'}]},
  {id: 2, name: 'c', tags: []},
  {id: 3, name: 'd', tags: [{id: 0, name: 'q'}, {id: 3, name: 'r'}, {id: 7, name: 'i'}]},
  {id: 6, name: 'g', tags: [{id: 7, name: 'i'}, {id: 4, name: 't'}]},
]

const tags = [
  {id: 0, name: 'q'},
  {id: 1, name: 'w'},
  {id: 2, name: 'e'},
  {id: 3, name: 'r'},
  {id: 4, name: 't'},
  {id: 7, name: 'i'},
  {id: 11, name: 's'}
]

let selectedTags = [0, 5]

selectedTags is an Array of indexes of tags Array. Now I need to find all objects in tasks Array, where property tags includes any of the selected tags. So in this case the output should be:

let result = [
  {id: 0, name: 'a', tags: [{id: 0, name: 'q'}, {id: 1, name: 'w'}]},
  {id: 3, name: 'd', tags: [{id: 0, name: 'q'}, {id: 3, name: 'r'}, {id: 7, name: 'i'}]},
  {id: 6, name: 'g', tags: [{id: 7, name: 'i'}, {id: 4, name: 't'}]}
]

I tried to do something like this:

let result= []
_.forEach(selectedTags, index => {
  const tagId = tags[index].id
  result = _.filter(tasks, task => _.some(task.tags, ['tag.id', tagId]))
})

but I'm ending up with an empty array. I tried to use map, find and some other lodash methods, but so far nothing worked.

Any ideas, please?

2
  • You're overwriting result each time through the _.forEach loop, not combining the results from previous iterations. Commented Feb 29, 2020 at 17:59
  • There's no tag property to match tag.id Commented Feb 29, 2020 at 18:00

2 Answers 2

1

You're reassigning the filtered array in each iteration, also you're passing to the function .some an array, however, you should pass a key-value object instead.

The following approach used two nested calls of function .some for checking tags.id vs selectedTag ids,

const tasks = [  {id: 0, name: 'a', tags: [{id: 0, name: 'q'}, {id: 1, name: 'w'}]},  {id: 1, name: 'b', tags: [{id: 2, name: 'e'}, {id: 4, name: 't'}, {id: 11, name: 's'}]},  {id: 2, name: 'c', tags: []},  {id: 3, name: 'd', tags: [{id: 0, name: 'q'}, {id: 3, name: 'r'}, {id: 7, name: 'i'}]},  {id: 6, name: 'g', tags: [{id: 7, name: 'i'}, {id: 4, name: 't'}]}],
      tags = [  {id: 0, name: 'q'},  {id: 1, name: 'w'},  {id: 2, name: 'e'},  {id: 3, name: 'r'},{id: 4, name: 't'},  {id: 7, name: 'i'},  {id: 11, name: 's'}],
      selectedTags = [0, 5],
      result = _.filter(tasks, ({tags: itags}) => _.some(itags, ({id}) => _.some(selectedTags, i => tags[i].id === id)));

console.log(result);
.as-console-wrapper {min-height: 100%;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.core.min.js"></script>

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

5 Comments

You need to remove duplicates from the result, it's returning ID:3 twice.
First of all thank you for your help! Much appreciated! Why did it return also object with ID 1? It doesn't have any of the selected tags
@Igal weird, with the destructuring assignment it generates that result, I updated the answer removing destructuring assignment.
@Ele Thank you very much! This time it worked as expected! BTW, your very first solution also worked, I just added result = _.uniqBy(result, 'id'). But the last solution is much cleaner! Again, thank you very much!
@Igal I saw the problem, it's because of the variable tags.
0

You need to use filter() with nested some()

const tasks = [
  {id: 0, name: 'a', tags: [{id: 0, name: 'q'}, {id: 1, name: 'w'}]},
  {id: 1, name: 'b', tags: [{id: 2, name: 'e'}, {id: 4, name: 't'}, {id: 11, name: 's'}]},
  {id: 2, name: 'c', tags: []},
  {id: 3, name: 'd', tags: [{id: 0, name: 'q'}, {id: 3, name: 'r'}, {id: 7, name: 'i'}]},
  {id: 6, name: 'g', tags: [{id: 7, name: 'i'}, {id: 4, name: 't'}]},
]

const tags = [
  {id: 0, name: 'q'},
  {id: 1, name: 'w'},
  {id: 2, name: 'e'},
  {id: 3, name: 'r'},
  {id: 4, name: 't'},
  {id: 7, name: 'i'},
  {id: 11, name: 's'}
]

let selectedTags = [0, 5]
const res = tasks.filter(({tags}) => 
               tags.some(tag => 
                  selectedTags.some(index => tags[index].name === tag.name)
               )
            );
console.log(res)

1 Comment

You're returning task ID 1, which doesn't match either of the selected tags.

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.