10

In the below, function redux1 removes entries corresponding to keys not listed in keys_to_keep from data object.

Given that I have a list of object keys to keep, how can I rewrite redux1 in a cleaner way, prefarably utilizing map, filter or reduce?

var data = [
    {name: 'John', city: 'London', age: 42},
    {name: 'Mike', city: 'Warsaw', age: 18},
    {name: 'Jim', city: 'New York', age: 22},
    {name: 'Celine', city: 'Tokyo', age: 54},
]

var keys_to_keep = ['name', 'city']

function redux1(data) {
    data.forEach((person) => {
        Object.keys(person).forEach((key) => {
            if (!keys_to_keep.includes(key)) {
                delete (person[key])
            }
        })
    })
    console.log(data)
}

function redux2(data) { 
    var reduced = data.filter(person => Object.keys(person).filter(key => keys_to_keep.includes(key)))
    console.log(reduced)
}

redux1(data)
//redux2(data)

My current redux2 will return objects will not remove age.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
barciewicz
  • 3,511
  • 6
  • 32
  • 72

6 Answers6

28

You could use a combination of Array#map and Array#reduce:

const data = [
 {name: 'John', city: 'London', age: 42},
 {name: 'Mike', city: 'Warsaw', age: 18},
 {name: 'Jim', city: 'New York', age: 22},
 {name: 'Celine', city: 'Tokyo', age: 54},
]

const keys_to_keep = ['name', 'city'];

const redux = array => array.map(o => keys_to_keep.reduce((acc, curr) => {
  acc[curr] = o[curr];
  return acc;
}, {}));

console.log(redux(data));
Zenoo
  • 12,670
  • 4
  • 45
  • 69
7

A version slightly shorter than the accepted answer using Array#map and Object.fromEntries():

const data = [
    {name: 'John', city: 'London', age: 42},
    {name: 'Mike', city: 'Warsaw', age: 18},
    {name: 'Jim', city: 'New York', age: 22},
    {name: 'Celine', city: 'Tokyo', age: 54},
]

const keys_to_keep = ['name', 'city'];

const redux1 = list => list.map(o => Object.fromEntries(
    keys_to_keep.map(k => [k, o[k]])
));

console.log(redux1(data));
zr0gravity7
  • 2,917
  • 1
  • 12
  • 33
Dragonfang
  • 343
  • 2
  • 8
  • Thanks. Useful :) I need also an exclusion. Pasted from your code with field excluded : `data.map(o => Object.fromEntries( Object.keys(o).filter((n) => ["age"].indexOf(n) < 0 ).map(k => [k, o[k]]) ))` – phili_b Jun 22 '22 at 13:54
  • 1
    @phili_b You could directly filter the `entries` instead of adding another map: `Object.fromEntries( Object.entries(o).filter(([k]) => !["age"].includes(k) ) )` – adiga Nov 10 '22 at 09:29
  • Ha yes, you're right :) – phili_b Nov 10 '22 at 19:25
3

use Array.map and Array.forEach inside it :

var data = [
 {name: 'John', city: 'London', age: 42},
 {name: 'Mike', city: 'Warsaw', age: 18},
 {name: 'Jim', city: 'New York', age: 22},
 {name: 'Celine', city: 'Tokyo', age: 54},
]

var keys_to_keep = ['name', 'city']

const result = data.map(e => {
  const obj = {};
  keys_to_keep.forEach(k => obj[k] = e[k])
  return obj;
});

console.log(result);
Taki
  • 17,320
  • 4
  • 26
  • 47
2

var data = [
 {name: 'John', city: 'London', age: 42},
 {name: 'Mike', city: 'Warsaw', age: 18},
 {name: 'Jim', city: 'New York', age: 22},
 {name: 'Celine', city: 'Tokyo', age: 54},
]

var keys_to_keep = ['name', 'city']

data=data.map(element => Object.assign({}, ...keys_to_keep.map(key => ({[key]: element[key]}))))

console.log(data)
Krzysztof Krzeszewski
  • 5,912
  • 2
  • 17
  • 30
0
data.reduce((r, c) => [ ...r, Object.entries(c).reduce((b, [k, v]) => keys_to_keep.includes(k) ? {...b, [k]: v } : b, {}) ],[])
A. Moynet
  • 450
  • 3
  • 8
0

You can use Object.entries

function objfilter(data,keys_to_keep){
    return Object.fromEntries(Object.entries(data).filter(a=>keys_to_keep.includes(a[0])))
}
const data = [
    {name: 'John', city: 'London', age: 42},
    {name: 'Mike', city: 'Warsaw', age: 18},
    {name: 'Jim', city: 'New York', age: 22},
    {name: 'Celine', city: 'Tokyo', age: 54},
]

const keys_to_keep = ['name', 'city'];

console.log(objfilter(data,keys_to_keep))
Rainb
  • 1,965
  • 11
  • 32