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

John
  • 21
  • 5

2 Answers2

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);
ProSheta
  • 175
  • 1
  • 10
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.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Thanks @CertainPerformance it worked well. But as you suggest, I'm using `map()` to avoid mutating the array. – John Feb 04 '21 at 04:35