I'll-Be-Back
I'll-Be-Back

Reputation: 10828

Key check in object

I have wrote a script to check any missing fields from the objects and then return Ids of Item that has missing fields.

It is returning:

[ '222', '333' ]

Which I expected to return:

['333']

Why is it returning 222 id as well?

function returnMissingData(items) {
    const missing = items.reduce(function(acc, item) {
        const fields = [
            'Cost',
            'Name'
        ];

        for(const key of fields) {
            if (!item[key] || item[key] === undefined) { 
                acc.push(item.Id);
                break;
            }
        }

        return acc;
    }, []);

    return missing;
}


console.log(returnMissingData([
    {
        Id: "111",
        Name: "Name 1",
        Cost: 100,
    },
    {
        Id: "222",
        Name: "Name 2",
        Cost: 0,
    },
    {
        Id: "333",
        Name: "Name 3",
    }
]));

Edit: It must have properties and it can not be false as Boolean.

Upvotes: 0

Views: 62

Answers (4)

charlietfl
charlietfl

Reputation: 171669

Alternate approach using filter/map.

Filter uses Array#some() to find any missing keys

function returnMissingData(items) {
      const fields = ['Cost','Name'];
      return items.filter(o => fields.some(k => !(k in o))).map(({Id}) => Id);      
}


console.log(returnMissingData([
    {
        Id: "111",
        Name: "Name 1",
        Cost: 100,
    },
    {
        Id: "222",
        Name: "Name 2",
        Cost: 0,
    },
    {
        Id: "333",
        Name: "Name 3",
    }
]));

Upvotes: 2

zfrisch
zfrisch

Reputation: 8660

The Solution:

Change:

if (!item[key] || item[key] === undefined) 

To:

if (item[key] === false || item[key] === undefined) 

Why is this happening?

As you're iterating through your keys you check for !item[key] - which equates to a check for falsy values. Falsy values, as implied by the name Fals-y, do not necessarily mean false. It is the same as saying:

item[key] == false

the above uses type coercion to verify if item[key] and false values are analogous. It will change a number through coercion and then check if it's falsy. In this case 0 is falsy.

By using:

item[key] === false

We remove type coercion from the code. It's more sane, and does exactly what you'd expect instead of guessing.


Working Code:

function returnMissingData(items) {
    const missing = items.reduce(function(acc, item) {
        const fields = [
            'Cost',
            'Name'
        ];

        for(const key of fields) {
            if (item[key] === false || item[key] === undefined) { 
                acc.push(item.Id);
                break;
            }
        }

        return acc;
    }, []);

    return missing;
}


console.log(returnMissingData([
    {
        Id: "111",
        Name: "Name 1",
        Cost: 100,
    },
    {
        Id: "222",
        Name: "Name 2",
        Cost: 0,
    },
    {
        Id: "333",
        Name: "Name 3",
    }
]));

Upvotes: 1

brubs
brubs

Reputation: 1357

Because !item[key] will be valid for falsy values like 0. As the object with ID 222 has a key with 0 it will match.

Instead, you should check if the object has the key provided with myObj.hasOwnProperty('key')

function returnMissingData(items) {
    const missing = items.reduce(function(acc, item) {
        const fields = [
            'Cost',
            'Name'
        ];

        for(const key of fields) {
            if (!item.hasOwnProperty(key) || item[key] === undefined) { 
                acc.push(item.Id);
                break;
            }
        }

        return acc;
    }, []);

    return missing;
}


console.log(returnMissingData([
    {
        Id: "111",
        Name: "Name 1",
        Cost: 100,
    },
    {
        Id: "222",
        Name: "Name 2",
        Cost: 0,
    },
    {
        Id: "333",
        Name: "Name 3",
    }
]));

Upvotes: 1

Maheer Ali
Maheer Ali

Reputation: 36574

You should use hasOwnProperty()

function returnMissingData(items) {
    const missing = items.reduce(function(acc, item) {
        const fields = [
            'Cost',
            'Name'
        ];

        for(const key of fields) {
            if (!item.hasOwnProperty(key)) { 
                acc.push(item.Id);
                break;
            }
        }

        return acc;
    }, []);

    return missing;
}


console.log(returnMissingData([
    {
        Id: "111",
        Name: "Name 1",
        Cost: 100,
    },
    {
        Id: "222",
        Name: "Name 2",
        Cost: 0,
    },
    {
        Id: "333",
        Name: "Name 3",
    }
]));

Upvotes: 0

Related Questions