Joelito
Joelito

Reputation: 95

Array conversion nested object

I would like to transform the following array:

 let errors = [
   {
     field: "data.time",
     message: "less length than allowed"
   },
   {
     field: "data.time",
     message: "wrong format"
   },
   {
     field: "data.age",
     message: "too young"
   },
   { 
     field: "data.age",
     message: "not enough information"
   }
];

Into:

[
  { time: "less_length_than_allowed <br> wrong_format"},
  { age: "too_young <br> not_enough_information"},
]

I basically want to remove the string "data." for each field attribute. And then merge the array, with common field as the object key and the concatenation of messages for the value.

This is what i have so far:

var removedData = errors.map(item => {
   item.field = item.field.slice(5);
   return item
});

var computedErrors = _.chain(removedData).groupBy('field').value();

Upvotes: 0

Views: 64

Answers (5)

Ori Drori
Ori Drori

Reputation: 191976

const errors = [{"field":"data.time","message":"less length than allowed"},{"field":"data.time","message":"wrong format"},{"field":"data.age","message":"too young"},{"field":"data.age","message":"not enough information"}];

const result = _(errors)
  .groupBy(({ field }) => field.split('.')[1])
  .mapValues((group) => 
    group.map(({ message }) => _.snakeCase(message))
    .join(' <br> ')
  )
  .map((value, key) => ({ [key]: value }))
  .value();

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.3/lodash.min.js"></script>

Upvotes: 0

stasovlas
stasovlas

Reputation: 7406

_.chain(errors)
    .groupBy('field') // group errors by field
    .mapValues(function(items, key) { // iterate grouped arrays
        return _.chain(items)
            .map('message') // get message value from each item
            .join('<br>') // join messages
            .thru(function(str) {
                return _.set({}, key.replace(/data./g, ''), str); // transform to object
            })
            .value();
    })
    .values() // get object values
    .value();

Upvotes: 0

Nenad Vracar
Nenad Vracar

Reputation: 122037

You can use reduce() in plain js to return the following result.

let errors = [{
  field: "data.time",
  message: "less length than allowed"
}, {
  field: "data.time",
  message: "wrong format"
}, {
  field: "data.age",
  message: "too young"
}, {
  field: "data.age",
  message: "not enough information"
}];

var o = {}
var result = errors.reduce(function(r, e) {
  var key = e.field.split('.')[1];
  var message = e.message.replace(/\s/g, '_');

  if (!o[key]) {
    o[key] = {[key]: message}
    r.push(o[key])
  } else {
    o[key][key] += ' <br> ' + message
  }
  return r;
}, [])

console.log(result)

Upvotes: 1

Andreas
Andreas

Reputation: 21881

let errors = [{
  field: "data.time",
  message: "less length than allowed"
}, {
  field: "data.time",
  message: "wrong format"
}, {
  field: "data.age",
  message: "too young"
}, {
  field: "data.age",
  message: "not enough information"
}];

var mappedData = errors.reduce((result, currentValue) => {
  let type = currentValue.field.split(/\./).pop(),
    message = currentValue.message.replace(/\s/g, "_")

  if (typeof result[type] === "undefined") {
    result[type] = message
  } else {
    result[type] += " <br> " + message;
  }

  return result;
}, {});

console.log(mappedData);

Upvotes: 0

Faouzi Oudouh
Faouzi Oudouh

Reputation: 820

You can do it like so:

var age = [];
var time = [];
var removedData = errors.forEach(element => {
 if(element.field.contains('time')){ time.push(element.message); }
 if(element.field.contains('age')){ age.push(element.message); }
});

var removedData = {
 age: age.join('<br>'),
 time: time.join('<br>'),
}; 

Upvotes: 0

Related Questions