0

I need to filter dogs and also the sitters inside this Array based on another Array sittersSelected. (It's ok to use es6). The problem for me is handling the nested array.

Not sure if it's possible but...

Data

dogs = [
  {
    name: 'Alice',
    sex: 'Female',
    breed: 'German Shepherd',
    sitters: [
      {
        id: '123',
        name: 'Abby'
      },
      {
        id: '456',
        name: 'Manny'
      },
      {
        id: '789',
        name: 'Mel'
      },
    ]
  },
  {
    name: 'Buckley',
    sex: 'Male',
    breed: 'Border Collie',
    sitters: [
      {
        id: '321',
        name: 'Gustavo'
      },
      {
        id: '654',
        name: 'Tommy'
      },
    ]
  },
  {
    name: 'Bear',
    sex: 'Male',
    breed: 'Mixed',
    sitters: [
      {
        id: '123',
        name: 'Abby'
      },
      {
        id: '135',
        name: 'Owen'
      },
    ]
  },
];

sittersSelected = ["Abby","Manny"];

Expected Output

filterResult = [
  {
    name: 'Alice',
    sex: 'Female',
    breed: 'German Shepherd',
    sitters: [
      {
        id: '123',
        name: 'Abby'
      },
      {
        id: '456',
        name: 'Manny'
      },
    ]
  },
  {
    name: 'Bear',
    sex: 'Male',
    breed: 'Mixed',
    sitters: [
      {
        id: '123',
        name: 'Abby'
      },
    ]
  },
];

I've tried

filterResult = dogs.filter(dog => dog.sitters.some(sitter => sittersSelected.includes(sitter.name)));

I managed to filter the dogs but not the sitters. Also tried other examples here on StackOverflow. Is there a way to do it? maybe with .map() ?

Thank you

2
  • How big can these two lists potentially be at their largest size? Commented Feb 4, 2021 at 1:49
  • @TobiahRex It is quite big, the data has more options... I just used dogs as an example. Commented Feb 4, 2021 at 4:33

2 Answers 2

1

1-use map to return new object contain only filtered sitters

2-use filter to return only dog have sitters

let dogs = [{ name: 'Alice', sex: 'Female', breed: 'German Shepherd', sitters: [{ id: '123', name: 'Abby' }, { id: '456', name: 'Manny' }, { id: '789', name: 'Mel' },] }, { name: 'Buckley', sex: 'Male', breed: 'Border Collie', sitters: [{ id: '321', name: 'Gustavo' }, { id: '654', name: 'Tommy' },] }, { name: 'Bear', sex: 'Male', breed: 'Mixed', sitters: [{ id: '123', name: 'Abby' }, { id: '135', name: 'Owen' },] },];

let sittersSelected = ["Abby", "Manny"];

dogs.map(dog => {
    return {
        ...dog,
        sitters: dog.sitters.filter(sitter => sittersSelected.includes(sitter.name))
    }
}).filter(dog => dog.sitters.length > 0);
Sign up to request clarification or add additional context in comments.

1 Comment

It worked, thank you so much @ProSheta
0

You'll need 2 steps.

  1. First filter each sitters sub-array to include only the ones selected.
  2. Filter out the parent array items by whether the sitters array contains any elements:

const dogs=[{name:"Alice",sex:"Female",breed:"German Shepherd",sitters:[{id:"123",name:"Abby"},{id:"456",name:"Manny"},{id:"789",name:"Mel"}]},{name:"Buckley",sex:"Male",breed:"Border Collie",sitters:[{id:"321",name:"Gustavo"},{id:"654",name:"Tommy"}]},{name:"Bear",sex:"Male",breed:"Mixed",sitters:[{id:"123",name:"Abby"},{id:"135",name:"Owen"}]}];

const sittersSelected = ["Abby","Manny"];

for (const dog of dogs) {
  dog.sitters = dog.sitters.filter(s => sittersSelected.includes(s.name));
}
const filteredDogs = dogs.filter(
  dog => dog.sitters.length
);
console.log(filteredDogs);

If you don't want to mutate the input array of objects, you can map it first to clone each dog.

1 Comment

Thanks @CertainPerformance it worked well. But as you suggest, I'm using map() to avoid mutating the array.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.