Chad
Chad

Reputation: 618

Filter array of objects based on array of objects returns same results

Goal is to remove the hardcoded database column names from my React component into a config file. Instead of using data.X it would be data.A as shown below. This way if they change X to something else I would just need to change the config file for X and then everywhere in my React component it will update, because data.A is in the component.

Problem is filtering returns only the last object in data. Any help would be appreciated, any suggestions on removing the nested for loop would be helpful for learning.

Desired output:

[
    {
        "A": 1,
        "B": 2,
    },
    {
        "A": 4,
        "B": 5,
    },
    {
        "A": 7,
        "B": 8,
    },
];

Current output:

[
    {
        "A": 7,
        "B": 8,
    },
    {
        "A": 7,
        "B": 8,
    },
    {
        "A": 7,
        "B": 8,
    },
];

fiddle

let data = [
    {
        "X": 1,
        "Y": 2,
        "Z": 3,
    },
    {
        "X": 4,
        "Y": 5,
        "Z": 6,
    },
    {
        "X": 7,
        "Y": 8,
        "Z": 9,
    },
];

let keys = {
    A: 'X',
    B: 'Y',
};
let keyChain = {};
let cleanedData = [];

for (let key in keys) {
    keyChain[key] = '';
}

for (let i in data) {
    cleanedData[i] = keyChain;
    for (let key in keys) {
        if (keys[key] in data[i]) {
            cleanedData[i][key] = data[i][keys[key]];
        };
    }
}
console.log(cleanedData);

Upvotes: 0

Views: 72

Answers (5)

AndreaM16
AndreaM16

Reputation: 3975

It's way easier to solve than expected. Simply use map.

let filteredData = data.map((item) => ({'A' : item.X, 'B' : item.Y}));

You are simply mapping element.X of each item to A and element.Y to B into a new object each time.

let data = [
    {
        "X": 1,
        "Y": 2,
        "Z": 3,
    },
    {
        "X": 4,
        "Y": 5,
        "Z": 6,
    },
    {
        "X": 7,
        "Y": 8,
        "Z": 9,
    },
];

let filteredData = data.map((item) => ({'A' : item.X, 'B' : item.Y}));
console.log(filteredData);

The script above takes 1496412529493.929ms to complete, while the one in the accepted answer takes 1496412584210.4958ms which is a bit slower.

Upvotes: 1

neojg
neojg

Reputation: 221

IMHO what you missed is that the keyChain object is used the same for each cleanedData array element. You must always remember that JavaScript uses references to objects so each line:

cleanedData[i] = keyChain; // same object
// ...
cleanedData[i][key] = data[i][keys[key]];
// modify keyChain object attributes

You have, in result, an array of references to the same object and the value is the last modification.

Try to use something like (ES5 way):

 cleanedData[i] = new Object(); // new object

Upvotes: 1

Ivo
Ivo

Reputation: 555

const data = [
    {
        "X": 1,
        "Y": 2,
        "Z": 3,
    },
    {
        "X": 4,
        "Y": 5,
        "Z": 6,
    },
    {
        "X": 7,
        "Y": 8,
        "Z": 9,
    },
];

const keys = {
    A: 'X',
    B: 'Y',
};

let keysReMap = {};
for (var [key, value] of Object.entries(obj)) {
    keysReMap[value] = key;
}

const cleanedData = data.map((val, key) => {
    const newKey = keysReMap[key];
    return {
        [newKey]: val
    };
});

Upvotes: 0

Omri Aharon
Omri Aharon

Reputation: 17064

That's because you're reusing the same keyChain object as your new placeholder, so that's the same object. You need to create a new one each time:

cleanedData[i] = { ...keyChain }; // instead of cleanedData[i] = keyChain;

Fiddle

Upvotes: 1

Geeky
Geeky

Reputation: 7498

Just change your last part of code to the following then you can achieve

for (let i in data) {
    cleanedData[i] ={}
    for (let key in keys) {
        if (keys[key] in data[i]) {
            cleanedData[i][key] = data[i][keys[key]];
        };
    }
}
console.log(cleanedData);

let data = [
    {
        "X": 1,
        "Y": 2,
        "Z": 3,
    },
    {
        "X": 4,
        "Y": 5,
        "Z": 6,
    },
    {
        "X": 7,
        "Y": 8,
        "Z": 9,
    },
];

let keys = {
    A: 'X',
    B: 'Y',
};
let keyChain = {};
let cleanedData = [];

// construct the placeholder key value pair array
for (let key in keys) {
    keyChain[key] = '';
}

// check keys to see if there's a match with the json
for (let i in data) {
    cleanedData[i] ={}
    for (let key in keys) {
        if (keys[key] in data[i]) {
            cleanedData[i][key] = data[i][keys[key]];
        };
    }
}
console.log(cleanedData);

Hope it helps

Upvotes: 1

Related Questions