Skip to content
Advertisement

Best way to Search ALL Terms in Array of Objects

I’m trying to filter out objects based on whether ALL the given search terms exist in SOME of the property values of EACH object in the array. But I also don’t want to search within the deviceId property.

But is there a way to do it with less code?

So I do the following:

  1. Convert the objects into iterable arrays
  2. Filter out the array to remove arrays withdeviceId
  3. Convert the arrays back into the Key/Value pair objects
let DeviceDtoArrayOfArray = [];

DeviceDtos.forEach((indiv) => {
  DeviceDtoArrayOfArray.push(Object.entries(indiv));
});
let DeviceDtoArrayOfArrayFiltered = [];
DeviceDtoArrayOfArray.forEach((indiv) =>
  DeviceDtoArrayOfArrayFiltered.push(
    indiv.filter((indiv) => indiv[0] !== "deviceId")
  )
);

let DeviceDtoArrayOfArrayFilteredObjects = [];

DeviceDtoArrayOfArrayFiltered.forEach((indiv) => {
  DeviceDtoArrayOfArrayFilteredObjects.push(Object.fromEntries(indiv));
});
  1. Define sample search term array
  2. For each object from Step 3, create an array of it’s property values
  3. Filter each Object in the array by searching each Search Term, check to see if it exists within some of the property values from Step 5, if it exists, then the object is returned to a new array, if not, it’s filtered out

Sample Array containing the objects with deviceId

const DeviceDtos = [
  {
    deviceId: 1,
    deviceName: "Device0000",
    hwModelName: "Unassigned",
    deviceTypeName: "Unassigned",
    serviceTag: "A1A"
  },...

Sample Search Terms

const searchTerms = ["HwModel", "A1A"];

Filter out objects based on Search Terms

const results = DeviceDtoArrayOfArrayFilteredObjects.filter((indiv) => {
  const propertiesValues = Object.values(indiv); // all property values

  return searchTerms.every((term) =>
    propertiesValues.some(
      (property) => property.toLowerCase().indexOf(term.toLowerCase()) > -1
    )
  );
});

console.log(results);

Answer

Map the array of devices to a new array, where one item is the device, and one is an array of strings composed from the keys and values (with the deviceId excluded with rest syntax).

Then, all you have to do is filter that array by whether .every one of the search terms is included in .some of those strings.

const DeviceDtos = [
  {
    deviceId: 1,
    deviceName: "Device0000",
    hwModelName: "Unassigned",
    deviceTypeName: "Unassigned",
    serviceTag: "A1A"
  },
  {
    notincluded: 'notincluded'
  }
];
const devicesAndStrings = DeviceDtos.map(
  ({ deviceId, ...obj }) => [obj, Object.entries(obj).flat()]
);
const searchTerms = ["hwModel", "A1A"];
const foundDevices = devicesAndStrings
  .filter(([, strings]) => searchTerms.every(
    term => strings.some(
      string => string.includes(term)
    )
  ))
  .map(([obj]) => obj);
console.log(foundDevices);
Advertisement