Problem
This is stripped down from a project I’m working on:
let userFields = {
id: {
dbFields: 'id',
},
email: {
dbFields: 'email',
},
first_name: {
dbFields: 'first_name',
},
last_name: {
dbFields: 'last_name',
},
name: {
dbFields: ['first_name', 'last_name'],
resolve: user => [user.first_name, user.last_name].filter(n => n.length).join(' '),
}
};
let selectFields = ['name', 'first_name', 'email'];
let dbFields = new Set();
selectFields.forEach(f => {
if(userFields[f].dbFields) {
if(userFields[f].dbFields instanceof Array) {
userFields[f].dbFields.forEach(x => dbFields.add(x));
} else {
dbFields.add(userFields[f].dbFields);
}
}
});
console.log(Array.from(dbFields)); // [ 'first_name', 'last_name', 'email' ]
I don’t like that big selectFields.forEach
or the fact that Set
doesn’t appear to have an addMany
method.
Is there any way I can compact this a bit more?
You can run this with babel-node if you need to (npm install -g babel
).
Solution
Taking advantage of Array.prototype.flat()
we might compact this a bit.
Basically, we filter all of our fields, making them an array if they are not already, getting out an array of arrays (nested only one level). After that, we can easily flatten it, so we iterate each element and we can just add it to our set.
let userFields = {
id: {
dbFields: 'id',
},
email: {
dbFields: 'email',
},
first_name: {
dbFields: 'first_name',
},
last_name: {
dbFields: 'last_name',
},
name: {
dbFields: ['first_name', 'last_name'],
resolve: user => [user.first_name, user.last_name].filter(n => n.length).join(' '),
}
};
let selectFields = ['name', 'first_name', 'email'];
let dbFields = new Set();
selectFields.map(key => {
let field = userFields[key].dbFields;
return (field instanceof Array) ? field : [field]
})
.flat()
.forEach(v => dbFields.add(v));
console.log(Array.from(dbFields));