Home > Net >  Fastest way to clean path collisions in array of strings
Fastest way to clean path collisions in array of strings

Time:02-21

This is a hard one to explain, but here goes. I need to clean an array of 'path' strings where if a path has sub properties it not include the top level property. but only the child properties

E.g

[
  'firstName',
  'address',
  'address.local.addressLine1',
  'address.local.addressLine2',
  'address.local',
]

Should become:

[
  'firstName',
  'address.local.addressLine1',
  'address.local.addressLine2',
  'address.local',
]

I have a fairly verbose function kind of working so far, but looking to see if there is a more elegant/better solution than this:

function cleanCollisions(array) {

        var output = [];

        // return [...new Set(array)];
        var map = array.reduce(function(set, field) {
            if (!Boolean(field)) {
                return set;
            }

            ////////////////

            var rootKey = field.split('.')[0];
            if(!set[rootKey]) {
                set[rootKey] =[];
            }

            var count = field.split('.').length -1;
            if(count) {
                set[rootKey].push(field);
            }


            return set;
        }, {})


        for(const key in map) {
            value = map[key];
            if(value.length) {
                output.push(value);
            } else {
                output.push(key);
            }
        }

        ////////////////

        return output.flat();
    }

CodePudding user response:

I'd first iterate over the array to extract the top property of all strings that have sub properties, then filter out all those top properties.

const input = [
  'firstName',
  'address',
  'address.local.addressLine1',
  'address.local.addressLine2',
  'address.local',
];

const topLevelProps = new Set();
for (const str of input) {
  const match = str.match(/^(.*?)\./);
  if (match) {
    topLevelProps.add(match[1]);
  }
}
const output = input.filter(str => !topLevelProps.has(str));
console.log(output);

CodePudding user response:

A variation of the answer by CertainPerformance but using filter and map instead of regex:

const paths = [
  'firstName',
  'address',
  'address.local.addressLine1',
  'address.local.addressLine2',
  'address.local',
];

const roots = paths.filter(p => p.includes('.')).map(p => p.split('.')[0]);
const cleansed = paths.filter(p => p.includes('.') || !roots.includes(p));

console.log(cleansed);

  • Related