user16860065
user16860065

Reputation:

Filter out array using another array of objects

I am having two arrays

const selected = [];
const current = [
  { id: 1, name: "abc" },
  { id: 2, name: "def" }
];
const result = []

I need to compare these two arrays and the result should only have the single entry instead of duplicates. In the above example result should have the following output.

Also items in the selected should be taken into consideration and should be in the beginning of the result

result = [
  { id: 1, name: "abc" },
  { id: 2, name: "def" }
];

Also when the input is following

const selected = [ {id:5, name: "xyz" }];
const current = [
  { id: 1, name: "abc" },
  { id: 2, name: "def" }
];
result = [[
  { id: 5, name: "xyz" },
  { id: 1, name: "abc" },
  { id: 2, name: "def" }
];

Also when the input is following

const selected = [ {id:1, name: "abc" }, {id:4, name: "lmn" }];
const current = [
  { id: 1, name: "abc" },
  { id: 2, name: "def" }
];
result = [[
  { id: 1, name: "abc" },
  { id: 4, name: "lmn" }
  { id: 2, name: "def" }
];

Note the comparison should be made using name field

Code that I tried

const res = [...(selected || [])].filter((s) =>
  current.find((c) => s.name === c.name)
);

Sandbox: https://codesandbox.io/s/nervous-shannon-j1vn5k?file=/src/index.js:115-206

Upvotes: 2

Views: 68

Answers (3)

mani
mani

Reputation: 3096

This is a good use for .reduce, avoids multiple loops/finds and doesn't need filtering with side-effects.

const selected = [ {id:1, name: "abc" }, {id:4, name: "lmn" }];
const current = [
  { id: 1, name: "abc" },
  { id: 2, name: "def" }
];

const result = Object.values(
  [...selected, ...current].reduce((obj, item) => {
    obj[item.name] = obj[item.name] || item;
    return obj;
  }, {})
)

console.log(result);

Upvotes: 0

Andy
Andy

Reputation: 63525

Loop through selected, and if there is no object in current with a name that matches the name of the object in the current iteration push it into current.

const selected=[{id:1,name:"abc"},{id:6,name:"def"},{id:4,name:"lmn"}];
const current=[{id:1,name:"abc"},{id:2,name:"def"}];

for (const sel of selected) {
  const found = current.find(cur => cur.name === sel.name);
  if (!found) current.push(sel);
}

console.log(current);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386654

You could get all items and filter the array by checking the name with a Set.

const
    filterBy = (key, s = new Set) => o => !s.has(o[key]) && s.add(o[key]),
    selected = [{ id: 1, name: "abc" }, { id: 1, name: "lmn" }],
    current = [{ id: 1, name: "abc" }, { id: 2, name: "def" }],
    result = [...selected, ...current].filter(filterBy('name'));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

Related Questions