Jamie Aden
Jamie Aden

Reputation: 981

filter existing array of object using simple map and filter es6

Try to avoid using any library as I just need a simple script. I want to get non existing record from existing array.

input = [{name: 'james'}, {name: 'jane'}]

existing = [{name: 'james'}]

//do something

expected input to become [{name: 'jane'}]

I tried this

let input = [{
      name: 'yahoo.com',
    },{
      name: 'google.my',
    }]

    existing = (existing || []).map(o => ({name: o.name})) //clean up data from backend [{name:'google.my'}]


    input = (input || []).map(o => o.name) //just in case input has more property in the future

    input = existing.filter(o => !o.name.includes(input))

    console.log(input)

Somehow I still don't get what I want (expect input to be [{name: 'yahoo.com'}], what is missing? I couldn't spot it.

Upvotes: 0

Views: 180

Answers (5)

Arman Charan
Arman Charan

Reputation: 5797

Array.prototype.filter, Array.prototype.map, and Set can be combined using a closure to detect missing elements between arrays of objects using keys.

See below for a practical example.

// Input.
const input = [{name: 'james'}, {name: 'jane'}]

// Existing.
const existing = [{name: 'james'}]

// Missing (B elements from A).
const missing = (A, B) => (s => A.filter(({name}) => !s.has(name)))(new Set(B.map(({name}) => name)))

// Output.
const output = missing(input, existing)

// Proof.
console.log(output)

Upvotes: 1

Adam Jenkins
Adam Jenkins

Reputation: 55613

First, don't reuse variable names, it's confusing (you have two separate things called input.

Second, don't do unnecessary loops. Do a filter right out of the gate and then map to get an array of names (or skip the map altogether if you don't really need it)

let input = [
    {
        name: 'yahoo.com'
    },
    {
      name: 'google.my'
    }
]

    //all names in existing that are also in input
    (existing || [])
         //I used some instead of includes
        .filter(o => !(input || []).some(i => i.name == o.name))
        .map(o => o.name);

MDN Array.prototype.some

Upvotes: -1

Eddie
Eddie

Reputation: 26844

You can use filter and find

let input = [{name: 'james'}, {name: 'jane'}];
let existing = [{name: 'james'}];

let result = input.filter(v => !existing.find(o => o.name == v.name));


console.log(result);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386560

You could filter with a lookup with find.

var input = [{ name: 'james' }, { name: 'jane' }],
    existing = [{ name: 'james' }],
    result = input.filter(({ name }) => !existing.find(o => o.name === name));
    
console.log(result);

Upvotes: 1

Zenoo
Zenoo

Reputation: 12880

You can use a combination of two Array#filter.

The first one is looping through your input array, while the second one loops through your existing array to check if each input value is contained inside existing.

let input = [{name: 'james'}, {name: 'jane'}];
let existing = [{name: 'james'}];

let res = input.filter(a => !existing.filter(b => b.name == a.name).length);
console.log(res);

Upvotes: 0

Related Questions