Skip to content
Advertisement

filter an array of objects in javascript, with siblings that match on a common key value

Suppose I have a javascript array of objects that looks like this:

[
    {
        "title": "The Great Peace",
        "copyversion": 1
    },
    {
        "title": "History of World War II",
        "copyversion": 1
    },
    {
        "title": "Crime and Punishment",
        "copyversion": 2
    },
    {
        "title": "War and Peace",
        "copyversion": 2
    }
]

Now, suppose that I have a search string, like “War” or “and”. I want to get an array of objects where “title” contains the search string (case insensitive), but I want to ALSO include any sibling values with matching “copyversion” values.

For example:

Search string of “Great” should yield the below result, because even though “History of World War II” does not have “Great” in it, it matches the copyversion of something that does.

[
    {
        "title": "The Great Peace",
        "copyversion": 1
    },
    {
        "title": "History of World War II",
        "copyversion": 1
    }
]

Another example:

Search string of “Peace” would yield the original array. “History of World War II” is included because it has the same copyversion value as “The Great Peace”, and “Crime and Punishment” is included because it has the same copyversion as “War and Peace”

[
    {
        "title": "The Great Peace",
        "copyversion": 1
    },
    {
        "title": "History of World War II",
        "copyversion": 1
    },
    {
        "title": "Crime and Punishment",
        "copyversion": 2
    },
    {
        "title": "War and Peace",
        "copyversion": 2
    }
]

If no matches are found, then an empty array would result.

I’m looking for a reasonable fast way to do this. I’m fine with pure javascript or a library like lodash.

Answer

Solution contains two parts:

  1. find all matching objects and collect their copyversion. Do not store duplicates.
  2. return all objects with the corresponding copyversion.

The first part may be optimized – we don’t have to remove duplicates.

const a = [
    {
        "title": "The Great Peace",
        "copyversion": 1
    },
    {
        "title": "History of World War II",
        "copyversion": 1
    },
    {
        "title": "Crime and Punishment",
        "copyversion": 2
    },
    {
        "title": "War and Peace",
        "copyversion": 2
    }
];

const copyFinder = (word, arr) => {
  const rx = new RegExp(`${word}`, 'i');
  const versions = arr.reduce((collector, value) => {
    if(rx.test(value.title) && collector.indexOf(value.copyversion) === -1) {
      collector.push(value.copyversion);
    }
    return collector;
  }, []);
  if(versions.length === 0) {
    return [];
  }
  return arr.filter(x => versions.indexOf(x.copyversion) > -1);
}

console.log(copyFinder('History', a));
Advertisement