1

I've got an object describing various dog types, as well as variables describing the dog I'm looking for:

const dogs = [
  {
    "breed": "german shepherd",
    "size": ["large"],
    "temperment": ["trait 1","trait 3"]
  },
  {
    "breed": "poodle",
    "size": ["small","medium","large"],
    "temperment": ["trait 1","trait 2","trait 3"]
  },
  {
    "breed": "terrier",
    "size": ["small","medium"],
    "temperment": ["trait 1","trait 2"]
  }
]

const idealSize = ["medium"] //ideal match can include other sizes as well
const idealTemperment = ["trait 1","trait 2"] //ideal match would possess NO other traits

I've got a specific dog size and dog temperament I'm looking for that both need to match. Dog temperament should match exactly.

Here's what I currently have:

const filteredDogs = dogs.find((dog) => {  
  return idealSize.every(e => dog.size.includes(e));
});

console.log(filteredDogs)

It's currently only looking for a "size" match, and I'm unsure of how to also match the "temperament" [exclusively].

The ideal outcome would be:

"breed": "terrier",
"size": ["small","medium"],
"temperment": ["trait 1","trait 2"]
Dean Arvin
  • 115
  • 6
  • ``ideal match can include other sizes as well`` what do you mean by this? – M A Salman Aug 27 '20 at 01:50
  • Apologies on the lack of clarity - what I mean is that if the idealSize = "medium", then the dog.size must include "medium" but could also include other sizes like "small" and "large". Contrary to temperament where is idealTemperament = "trait1" then dog.temperament should ONLY include "trait1". – Dean Arvin Aug 27 '20 at 01:52

3 Answers3

2

To reduce computational complexity, make a Set of the idealTemperment, then check that .every of a dog's temperment array exists in that Set, and that their sizes are the same:

const dogs = [
  {
    "breed": "german shepherd",
    "size": ["large"],
    "temperment": ["trait 1","trait 3"]
  },
  {
    "breed": "poodle",
    "size": ["small","medium","large"],
    "temperment": ["trait 2","trait 3"]
  },
  {
    "breed": "terrier",
    "size": ["small","medium"],
    "temperment": ["trait 1","trait 2"]
  }
];
const idealSize = ["medium"] //ideal match can include other sizes as well
const idealTemperment = ["trait 1","trait 2"] //ideal match would possess NO other traits
const sizeSet = new Set(idealSize);
const tempermentSet = new Set(idealTemperment);
const filteredDogs = dogs.find(dog => (
  dog.size.some(size => sizeSet.has(size)) &&
  dog.temperment.length === tempermentSet.size &&
  dog.temperment.every(trait => tempermentSet.has(trait))
));

console.log(filteredDogs)
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Using include with array has more complexity than a has with Set? How? Will you explain or direct me to some sources, so that I can understand – M A Salman Aug 27 '20 at 01:57
  • 3
    @Supercool.See https://stackoverflow.com/questions/55057200/is-the-set-has-method-o1-and-array-indexof-on and https://stackoverflow.com/questions/31091772/javascript-es6-computational-time-complexity-of-collections. Set.has is `O(1)`, `Array.includes` is `O(n)` – CertainPerformance Aug 27 '20 at 01:58
  • With only one or two temperaments or sizes, I imagine that despite the reduced time complexity, constructing a set would be slower. – Rubydesic Aug 27 '20 at 02:02
1

You can use the every operation on idealTemperment as well. But to make sure that "ideal match would possess NO other traits", you should verify that the number of traits of a dog type is equal to the number of expected traits as well.

const dogs = [
  {
    "breed": "german shepherd",
    "size": ["large"],
    "temperment": ["trait 1","trait 3"]
  },
  {
    "breed": "poodle",
    "size": ["small","medium","large"],
    "temperment": ["trait 1","trait 2","trait 3"]
  },
  {
    "breed": "terrier",
    "size": ["small","medium"],
    "temperment": ["trait 1","trait 2"]
  }
]

const idealSize = ["medium"];
const idealTemperment = ["trait 1","trait 2"];

const filteredDogs = dogs.find((dog) => {  
  return idealSize.every(e => dog.size.includes(e)) &&
  (idealTemperment.every(e => dog.temperment.includes(e))) &&
  (idealTemperment.length === dog.temperment.length);
});

console.log(filteredDogs);
Udith Gunaratna
  • 2,091
  • 1
  • 13
  • 17
0

Use Array#filter for filtering the desired dogs. Additional needed is Array#some to find all dogs where at least one size matches to the idealsizes. last there is needed Array#every to look that every temeperament from the dog is contained it the wished temperements. Because the temeprament should match exactly compare the sizes of both arrays.

const dogs = [
  {
    "breed": "german shepherd",
    "size": ["large"],
    "temperment": ["trait 1","trait 3"]
  },
  {
    "breed": "poodle",
    "size": ["small","medium","large"],
    "temperment": ["trait 1","trait 2","trait 3"]
  },
  {
    "breed": "terrier",
    "size": ["small","medium"],
    "temperment": ["trait 1","trait 2"]
  }
]

const idealSize = ["medium"] //ideal match can include other sizes as well
const idealTemperment = ["trait 1","trait 2"] //ideal match would possess NO other traits

let res = dogs.filter(dog => dog.size.some(size =>
    idealSize.includes(size)) &&
    idealTemperment.length === dog.temperment.length &&
    dog.temperment.every(temper => idealTemperment.includes(temper))
);

console.log (res);
Sascha
  • 4,576
  • 3
  • 13
  • 34