dev_054
dev_054

Reputation: 3718

Javascript - Building conditions dynamically

I created a general function called unique() to remove duplicates from a specific array.

However I'm facing a problem: I want to build the conditions dynamically based on properties that I pass to the function.

Ex: Let's suppose that I want to pass 2 properties, so I want to check these 2 properties before "remove" that duplicated object.

Currently I'm using eval() to build this condition "&&", however according to my search it's really a bad practice.

So, my question is:

What's the proper way to do this kind of thing?

Below is my current code:

function unique(arr, ...props) {
  const conditions = [];
  for (let prop of props) {
    conditions.push(`element['${prop}'] === elem['${prop}']`);
  }
  const condStr = conditions.join(' && ');

  return arr.filter((element, index) => {
    const idx = arr.findIndex((elem) => {
      return eval(condStr);
    });

    return idx === index;
  });
}

const arr1 = [{
  id: 1,
  name: 'Josh',
  description: 'A description'
}, {
  id: 2,
  name: 'Hannah',
  description: 'A description#2'
}, {
  id: 1,
  name: 'Josh',
  description: 'A description#3'
}, {
  id: 5,
  name: 'Anyname',
  description: 'A description#4'
}];

const uniqueValues = unique(arr1, 'id', 'name');
console.log('uniqueValues', uniqueValues);

Upvotes: 3

Views: 101

Answers (2)

parallaxis
parallaxis

Reputation: 196

This question is a bit subjective as far as implementation details, but the better way if you ask me is to pass in a callback function to hand over to filter.

In doing it this way, you can compose the function anyway you see fit. If you have a complex set of conditions you can use composition to build the conditions in the function before you pass it into your unique function https://hackernoon.com/javascript-functional-composition-for-every-day-use-22421ef65a10

A key to function composition is having functions that are composable. A composable function should have 1 input argument and 1 output value.

The hackernoon article is pretty good and goes much further in depth.

this will return a single function that applies all of your preconditions

function unique(arr, callback) {
  return arr.filter(callback);
}

const compose = (...functions) => data =>
  functions.reduceRight((value, func) => func(value), data)

unique(
    [1, 3, 4, 5 ,7, 11, 19teen]
    compose(
        (someStateCondition) => { /** return true or false **/ }, 
        (result) => { /** return result  === someOtherStateCondition **/}
    )
)

Upvotes: 2

Felix Kling
Felix Kling

Reputation: 816462

Use Array#every to compare all properties inline:

function unique(arr, ...props) {
  return arr.filter((element, index) => {
    const idx = arr.findIndex(
      elem => props.every(prop => element[prop] === elem[prop]);
    );
    return idx === index;
  });
}

Upvotes: 1

Related Questions