• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
    • Questions
    • Teachers
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

136
Views
How to filter an array of objects based on multiple properties in JavaScript/Typescript?

What is the best way to filter an array of objects based on multiple property conditions and preserve the original order. So what has to happen is to filter the array based on these two conditions:

  • Most recent version
  • Valid ones { invalid: false }

In other words leave only the valid ones and ones with highest version number(version number could be any).

const arr = [
  { name: 'John',   invalid: false, version: 1 },
  { name: 'John',   invalid: false, version: 2 },
  { name: 'John',   invalid: true,  version: 1 },
  { name: 'John',   invalid: true,  version: 5 },
  { name: 'John',   invalid: true,  version: 2 },
  { name: 'Samuel', invalid: false, version: 1 },
  { name: 'Samuel', invalid: false, version: 2 },
  { name: 'Samuel', invalid: true,  version: 1 },
];

to...

const arr = [
  { name: 'John',   invalid: false, version: 2 },
  { name: 'Samuel', invalid: false, version: 2 }
];

Thanks in advance!

almost 3 years ago · Santiago Trujillo
3 answers
Answer question

0

You can do it using Array.prototype.reduce.

Update the object corresponding to a particular name only if:

  • it's valid
  • it's new
  • it has a higher version that the currently stored object

const data = [
  { name: "John", invalid: false, version: 1 },
  { name: "John", invalid: false, version: 2 },
  { name: "John", invalid: true, version: 1 },
  { name: "John", invalid: true, version: 5 },
  { name: "John", invalid: true, version: 2 },
  { name: "Samuel", invalid: false, version: 1 },
  { name: "Samuel", invalid: false, version: 2 },
  { name: "Samuel", invalid: true, version: 1 },
];

const result = Object.values(
  data.reduce((acc, d) => {
    if (d.invalid) return acc;
    if (!acc[d.name] || d.version > acc[d.name].version) {
      acc[d.name] = d;
    }
    return acc;
  }, {})
);

console.log(result);

In TS, you can create separate types for valid and invalid data using the union type.

type ValidData = { name: string; invalid: false; version: number };
type InvalidData = { name: string; invalid: true; version: number };

const data: (ValidData | InvalidData)[] = [
  { name: "John", invalid: false, version: 1 },
  { name: "John", invalid: false, version: 2 },
  { name: "John", invalid: true, version: 1 },
  { name: "John", invalid: true, version: 5 },
  { name: "John", invalid: true, version: 2 },
  { name: "Samuel", invalid: false, version: 1 },
  { name: "Samuel", invalid: false, version: 2 },
  { name: "Samuel", invalid: true, version: 1 },
];

const result = Object.values(
  data.reduce((acc: { [name: string]: ValidData }, d) => {
    if (d.invalid) return acc;
    if (!acc[d.name] || d.version > acc[d.name].version) {
      acc[d.name] = d;
    }
    return acc;
  }, {})
);

console.log(result);
almost 3 years ago · Santiago Trujillo Report

0

I'd recommend doing this in several stages. Assuming that the order of the array isn't important, you can .sort it so the most recent version is first, and keep track of which you have added, and also filter out invalid ones. Something like this:

function filterThing(thing) {
  const added = new Set();
  return thing.sort((a, b) => b.version - a.version).filter((item) => {
    if (thing.invalid || added.has(thing.name)) {
      return false;
    }
    added.add(thing.name);
    return true;
  }
}

If you need to have the items in another order, you could sort after that. If you need to preserve the original order of the items, that's a more complicated algorithm.

almost 3 years ago · Santiago Trujillo Report

0

You could just use a lookup table, this is in O(n) runtime.

Basically iterate once through the array, remember for each valid name the highest version you saw, and then use that table as a filter for the original array.

const lookup = {} as Record<string, {name: string, version: number, invalid: boolean}>;
arr.forEach((it) => {
  const stored = lookup[it.name];
  if (stored) {
    if (!it.invalid && it.version > stored.version) {
      lookup[it.name] = it;
    }
  } else {
    lookup[it.name] = it;
  }
})

const filtered = arr.filter((it) => {
  const stored = lookup[it.name];
  const result = !it.invalid && it.version === stored.version;
  if (result) {  //if no duplicates wanted
    delete lookup[it.name];
  }
  return result;
});
almost 3 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error