1

I want to filter an array of objects, by a specific value within the objects.

In the example i've provided I want to filter the array 'pets' by a value in the array 'characteristics'. For example, where I have called the function with the param 'loyal', i'd only expect the object for the dog value to be returned, as only the dog has that characteristic.

At the moment when I call the function both objects are returned even though only the object for dog has that value in its characteristics array.

const pets = [
  {
    name: 'dog',
    characteristics: [
      {
        value: 'loyal'
      },
      {
        value: 'big'
      }
    ]
  },
  {
    name: 'cat',
    characteristics: [
      {
        value: 'fluffy'
      },
      {
        value: 'small'
      }
    ]
  },
  ]

function filterPets(pets, characteristic) {
  return pets.filter(function(pet) {
    return pet.characteristics.filter(o => o.value.includes(characteristic));
  })
}

console.log(filterPets(pets, 'loyal'));

2
  • 1
    return pet.characteristics.filter(o => o.value.includes(characteristic)).length. Commented Jul 26, 2021 at 14:11
  • 1
    @Lain - There's no reason to create an array and go through all the values when we have some instead. :-) Commented Jul 26, 2021 at 14:11

2 Answers 2

4

That's because for the characteristics check you're using filter, which always returns an array (even if a blank one), and even a blank array is a truthy value, so the outer filter keeps every pet you check. For that inner check, you want some, not filter, so you get a flag for whether any entries matched:

function filterPets(pets, characteristic) {
  return pets.filter(function(pet) {
    return pet.characteristics.some(o => o.value.includes(characteristic));
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^
  });
}

const pets = [
  {
    name: 'dog',
    characteristics: [
      {
        value: 'loyal'
      },
      {
        value: 'big'
      }
    ]
  },
  {
    name: 'cat',
    characteristics: [
      {
        value: 'fluffy'
      },
      {
        value: 'small'
      }
    ]
  },
];

function filterPets(pets, characteristic) {
  return pets.filter(function(pet) {
    return pet.characteristics.some(o => o.value.includes(characteristic));
  });
}

console.log(filterPets(pets, 'loyal'));


Just for what it's worth, I assume characteristics are unique (you can't have "loyal" twice), so you might prefer to keep those in a Set so you can check for them more easily than .some(o => o.includes(characteristic)). For instance:

const pets = [
    {
        name: "dog",
        characteristics: new Set(["loyal", "big"]),
    },
    {
        name: "cat",
        characteristics: new Set(["fluffy", "small"]),
    },
];

function filterPets(pets, characteristic) {
    return pets.filter(function(pet) {
        return pet.characteristics.has(characteristic);
    });
}

Live Example:

const pets = [
    {
        name: "dog",
        characteristics: new Set(["loyal", "big"]),
    },
    {
        name: "cat",
        characteristics: new Set(["fluffy", "small"]),
    },
];

function filterPets(pets, characteristic) {
    return pets.filter(function(pet) {
        return pet.characteristics.has(characteristic);
    });
}

console.log(filterPets(pets, "loyal"));
console.log("Don't worry about the {} for characteristics, the Stack Snippets console doesn't know how to display Set objects. Look in the real console if you want to double-check the set.");

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

2 Comments

As someone that spent too much time in Ie6 those , still trigger me :p
@JavaScript - LOL!
0
    function filterPets(list, charValue) {
      const filteredPets = []
        list.map(function(pet,petIndex,array) {
          pet.characteristics.map(function(charac){
            if(charac.value === charValue){
              return filteredPets.push(array[petIndex])
            }
         })
      })
      return filteredPets
    }

    filterPets(pets,'loyal');

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.