nirvair
nirvair

Reputation: 4180

filter the object key and create new nested keys

I have an array of parameters like this:

[param1, param2_experience, param3]

I have another array of objects like this:

[
  {
    id: 123,
    param1_issue: "some",
    param1_star: 5,
    param2_experience_time_taken: "45 minutes",
    param3_issue_other: "some other"
  },
  {
    id: 456,
    param1_issue: "some issue",
    param1_star: 3.5,
    param3_issue_other: "some other issue"
  }
]

I want to spilt this array basis on the first array. something like this:

[
  {
    id: 123,
    param1: {
      issue: "some",
      star: 5
    },
    param2_experience: {
       time_taken: "45 minutes"
    },
    param3: {
       issue_other: "some other"
    }
  },
  {
    id: 456,
    param1: {
      issue: "some issue",
      star: 3.5
    },
    param3: {
       issue_other: "some other issue"
    }
  }
]

What would be a better way to do it? This array can contain thousands of objects.

Upvotes: 0

Views: 78

Answers (3)

ryeballar
ryeballar

Reputation: 30088

You can make use of lodash#map and lodash#reduce to iterate the collection and the items of each collection, while lodash#set returns the newly transformed objects of the collection. They key point here is to replace the first _ of the keys using String.prototype.replace.

var result = _.map(data, function(item) {
  return _.reduce(item, function(result, value, key) {
    return _.set(result, key.replace('_', '.'), value);
  }, {});
});

var data = [
  {
    id: 123,
    param1_issue: "some",
    param1_star: 5,
    param2_experience_time_taken: "45 minutes",
    param3_issue_other: "some other"
  },
  {
    id: 456,
    param1_issue: "some issue",
    param1_star: 3.5,
    param3_issue_other: "some other issue"
  }
];

var result = _.map(data, function(item) {
  return _.reduce(item, function(result, value, key) {
    return _.set(result, key.replace('_', '.'), value);
  }, {});
});

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdn.jsdelivr.net/lodash/4.14.1/lodash.min.js"></script>

Upvotes: 1

castletheperson
castletheperson

Reputation: 33466

You can map each element in the array to a new object that has the format from you first array.

var keys = ["param1", "param2_experience", "param3"];
var data = [{"id":123,"param1_issue":"some","param1_star":5,"param2_experience_time_taken":"45 minutes","param3_issue_other":"some other"},{"id":456,"param1_issue":"some issue","param1_star":3.5,"param3_issue_other":"some other issue"}];

var output = _.map(data, e => {
  var obj = {};
  _.forIn(e, (val, key) => {
    var bucket = _.find(keys, k => _.startsWith(key, k));
    _.set(obj,
          bucket 
            ? [bucket, key.slice(bucket.length + 1)]
            : key,
          val);
  });
  return obj;
});

console.log(output);
<script src="https://cdn.jsdelivr.net/lodash/4.14.1/lodash.min.js"></script>

Upvotes: 1

Redu
Redu

Reputation: 26161

I guess you can do like this;

var arr = ["param1", "param2_experience", "param3"],
    brr = [
           {id: 123, param1_issue: "some", param1_star: 5, param2_experience_time_taken: "45 minutes", param3_issue_other: "some other"},
           {id: 426, param1_issue: "some issue", param1_star: 3.5, param3_issue_other: "some other issue"}
          ],
 merged = brr.map(o => { var obj = {id:o.id};
                         for(var key in o){
                           arr.forEach(k => {var prob = key.split(k+"_")[1];
                                             prob !== void 0 && (!obj[k] ? obj[k] = {[prob]: o[key]}
                                                                         : obj[k][prob] = o[key]);
                                            });
                         }
                         return obj;
                       });
console.log(merged);

Upvotes: 1

Related Questions