JABedford
JABedford

Reputation: 103

How To Use an Array to Pull Values from an Array of Objects

I have an array of reasons a password has failed validation:

const failures = schema.validate(password.value, { list: true });
console.log(failues);
// => [ 'min', 'uppercase', 'digits' ]

I also have an array of objects. The key is always a potential value of the failures array:

const msg = [
  { key: 'min', message: 'minimum' },
  { key: 'max', message: 'maximum' },
  { key: 'uppercase', message: 'need a uppercase' },
  { key: 'lowercase', message: 'need a lowercase' },
  { key: 'digits', message: 'must have digits' },
  { key: 'spaces', message: 'no spaces' },
  { key: 'oneOf', message: 'is not one of' },
];

I want to map over the failures array and return the relevant message from msg to display a more coherent error message.

Upvotes: 1

Views: 55

Answers (4)

Thomas
Thomas

Reputation: 12637

// this is a very verbose way to store this information, also hard to fetch by key
const msg = [
  { key: 'min', message: 'minimum' },
  { key: 'max', message: 'maximum' },
  { key: 'uppercase', message: 'need a uppercase' },
  { key: 'lowercase', message: 'need a lowercase' },
  { key: 'digits', message: 'must have digits' },
  { key: 'spaces', message: 'no spaces' },
  { key: 'oneOf', message: 'is not one of' },
];

const failures = [
  'min',
  'uppercase',
  'digits',
  'something-not-mapped'
];


// better use a map
const msg2 = msg.reduce((acc, item) => {
  acc[item.key] = item.message;
  return acc;
}, {});
console.log("msg2:", msg2);

// now you can do:
console.log("mapped failures:", failures.map(key => msg2[key] || key));
.as-console-wrapper{top:0;max-height:100%!important}

I think with the comments, this code is self-explanatory.

Upvotes: 0

Michael Bianconi
Michael Bianconi

Reputation: 5232

For each value in failures, pull the corresponding item from msg. However, may I suggest creating msg as a dict?

const msg = {
  'min': 'minimum',
  'max': 'maximum',
  ...
};

This will make it easier to do this.

failures.forEach((failure) => {
  if (failure in msg) {
    console.log(msg[failure]);
  }
});

Upvotes: 2

laruiss
laruiss

Reputation: 3816

const failures = schema.validate(password.value, { list: true });
console.log(failures);
// => [ 'min', 'uppercase', 'digits' ]

const msg = [
  { key: 'min', message: 'minimum' },
  { key: 'max', message: 'maximum' },
  { key: 'uppercase', message: 'need a uppercase' },
  { key: 'lowercase', message: 'need a lowercase' },
  { key: 'digits', message: 'must have digits' },
  { key: 'spaces', message: 'no spaces' },
  { key: 'oneOf', message: 'is not one of' },
];

const listOfMessages = msgs
  .filter(msg => failures.includes(msg.key)) // Get the appropriate object matching the error
  .map(msg => msg.message) // Only get the message

console.log(listOfMessages) // ['minimum', 'need a uppercase', 'must have digits']

Upvotes: 2

r3wt
r3wt

Reputation: 4742

You can use array.filter() and array.map() to achieve what you want:

const messages = msg.filter(r=>failures.indexOf(r.key)!==-1).map(r=>r.message)// ["minimum", "need a uppercase", "must have digits"]

What you do with it from here is up to you, as even if you join the messages array, it doesn't form a coherent sentence. I also agree with the recommendation above to switch to a Dict like Object instead of the array of objects you are using now.

Upvotes: 1

Related Questions