elzi
elzi

Reputation: 5672

Lodash - Determine if array of object includes a value specified in a 2-dimensional array of strings

I have an array of required field names where the presence of either/any would count as valid. I am representing this in a 2-dimensional array as such:

const REQUIRED_FIELDS = [
  ['amount', 'presets'],
  ['payment_types', 'credit_card']
]

I am comparing this against an array of objects that that look as such:

const FIELDS = [
  {
    type: 'name',
    label: 'Your Name'
  },
  {
    type: 'credit_card',
    label: 'Credit Card'
  }
]

Invalid Example

const FIELDS = [
  {
    type: 'name',
    label: 'Your Name'
  },
  {
    type: 'credit_card',
    label: 'Credit Card'
  }
]

This would be invalid as we have one from the second set (credit_card) but not the first (amount, presets)

Valid Example

const FIELDS = [
  {
    type: 'name',
    label: 'Your Name'
  },
  {
    type: 'credit_card',
    label: 'Credit Card'
  },
  {
    type: 'amount',
    label: 'Amount'
  }
]

We have one from each here.

Desired Result

I think I can get this done with Lodash's some and includes, but I'm having a major brain fart. Any help is appreciated.

Edit:

Solution

Here's what ended up working for me. I'm sure this could be more optimized.

function validity(fields) {
  const validityMap = REQUIRED_FIELDS.map(arr =>
    fields.map(obj => {
      return obj.type, arr.indexOf(obj.type) > -1
    })
  )
  return validityMap.map(y => y.indexOf(true) > -1)
}

Thanks to Mr Greek for getting me there.

Upvotes: 1

Views: 540

Answers (2)

Koushik Chatterjee
Koushik Chatterjee

Reputation: 4175

why don't you simply filter the require fields (with reference to your 2nd output type)

REQUIRED_FIELDS.filter(function(el){
    return !FIELDS.some(function(o){
        return el.indexOf(o.type)>-1;
    })
})

const REQUIRED_FIELDS = [
  ['amount', 'presets'],
  ['payment_types', 'credit_card']
];
const FIELDS_1 = [
  {
    type: 'credit_card',
    label: 'Credit Card'
  }
];
const FIELDS_2 = [
  {
    type: 'credit_card',
    label: 'Credit Card'
  },
  {
    type: 'amount',
    label: 'Amount'
  }
];
const FIELDS_3 = [
  {
    type: 'presets',
    label: 'Presets'
  }
];

function getValidity(fields) {
    return REQUIRED_FIELDS.filter(function(el) {
      return !fields.some(function(o) {
        return el.indexOf(o.type)>-1;
      });
    });
}

console.log(getValidity(FIELDS_1));
console.log(getValidity(FIELDS_2));
console.log(getValidity(FIELDS_3));

And if you want a empty array for the required fields that are present, then just change the .filter with a .map simply and change the return value as expected in map instead of filter

const REQUIRED_FIELDS = [
  ['amount', 'presets'],
  ['payment_types', 'credit_card']
];
const FIELDS_1 = [
  {
    type: 'credit_card',
    label: 'Credit Card'
  }
];
const FIELDS_2 = [
  {
    type: 'credit_card',
    label: 'Credit Card'
  },
  {
    type: 'amount',
    label: 'Amount'
  }
];
const FIELDS_3 = [
  {
    type: 'presets',
    label: 'Presets'
  }
];

function getValidity(fields) {
    return REQUIRED_FIELDS.map(function(el) {
      return fields.some(function(o) {
        return el.indexOf(o.type)>-1;
      }) ? [] : el;
    });
}

console.log(getValidity(FIELDS_1));
console.log(getValidity(FIELDS_2));
console.log(getValidity(FIELDS_3));

Upvotes: 1

Djaouad
Djaouad

Reputation: 22766

You can use map():

const REQUIRED_FIELDS = [
  ['amount', 'presets'],
  ['payment_types', 'credit_card']
];
const FIELDS_1 = [
  {
    type: 'credit_card',
    label: 'Credit Card'
  }
];
const FIELDS_2 = [
  {
    type: 'credit_card',
    label: 'Credit Card'
  },
  {
    type: 'amount',
    label: 'Amount'
  }
];
const FIELDS_3 = [
  {
    type: 'presets',
    label: 'Presets'
  }
];
function validity(fields) {
  return fields.map((obj) =>
    REQUIRED_FIELDS.map((arr) =>
      arr.indexOf(obj.type)>-1
    )
  );
}
console.log(validity(FIELDS_1));
console.log(validity(FIELDS_2));
console.log(validity(FIELDS_3));

Upvotes: 1

Related Questions