Building a unique array of db fields

Posted on

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));
  

Leave a Reply

Your email address will not be published. Required fields are marked *