Question

I have an array of objects:

var arr = [
  {field1: value, field2: value, field3: value, field4: value},
  {field1: value, field2: value, field3: value, field4: value},
  {field1: value, field2: value, field3: value, field4: value}
];

I need to break it into 2 arrays of objects: one containing objects that have only field1 and field 3, and one containing objects that have all the rest. I'm trying to use Underscore (well, actually LoDash - but they're the same) and so far, all I got is:

var arr1 = [], arr2 = [];
_.forEach(arr, function(line) {
    arr1.push(_.pick(line, ['field1', 'field3']));
    arr2.push(_.omit(line, ['field1', 'field3']));
});

While this code works it strikes me as very inefficient. I'm sure I'm missing an Underscore function that can make my life easier, my code more readable, and my program more efficient.

Was it helpful?

Solution

I don't think this is easier to read or more efficient then what you have written. But it does use underscore.

var arrs = _.reduce(arr, function(memo, item){

  var firstArr = _.chain(_.first(memo)).push(_.pick(item, ['field1', 'field3'])).value();
  var secondArr = _.chain(_.last(memo)).push(_.omit(item, ['field1', 'field3'])).value();

  return [ firstArr, secondArr ];

}, [[], []]);

OTHER TIPS

var input = [
  {field1: value, field2: value, field3: value, field4: value},
  {field1: value, field2: value, field3: value, field4: value},
  {field1: value, field2: value, field3: value, field4: value}
];

/* Generic function to get key-value pair form array of object.
 input >> is array of object.
 keys >> array of string keys.
 isNotRequired >> boolean flag whether output contains the keys which are provided or the keys except which are provided.
*/

function getKeyValues(input, keys, isNotRequired) {
    if (!keys || !keys.length) {
        return input;
    }
    return _.reduce(input, function(output, values) {
        output.push(_.reduce(values, function(object, value, key) {
            if (!isNotRequired) {
                if (keys.indexOf(key) > -1) {
                    object[key] = value;
                }
            } else if (keys.indexOf(key) === -1) {
                object[key] = value;
            }
            return object;
        }, {}));
        return output;
    }, []);
}

//In your example hot to use the function:

var FirstArrayWithField1AndField2 = getKeyValues(input,['field1','field2']);
var SecondArrayWithoutField1AndField2 = getKeyValues(input,['field1','field2'],true);

Underscore uses native Array.prototype.forEach method for its alias _.forEach. If it is not present somehow then it would define its own forEach iterator using the simple for loop. Apparently the performance of native forEach isn't that great to the simple for loop. That's because the native forEach performs a lot of checks while iterating.

I can only suggest that you re define _.forEach method like this -

_.forEach = function(obj, iterator, context) {
    if (obj == null) return;
    if (obj.length === +obj.length) {
        for (var i = 0, l = obj.length; i < l; i++) {
            if (iterator.call(context, obj[i], i, obj) === breaker) return;
        }
    }
}

Hope this answers your question. Happy Coding!

var arrs = _.groupBy(arr, function(obj) {
    return 'field1' in obj && 'field3' in obj;
});

This will return an object with properties named true and false.

var i ,target,length = arr.length, arr1 = [], arr2 = [];
for(i = 0; i< length;i++){
  target = arr[i];
  arr1.push({
    field1: target.field1, 
    field3: target.field3:
  });
  arr2.push({
    field2: target.field2, 
    field4: target.field4:
  });
}
var myarr = 
[
      {'field1': 'val01', 'field2': 'val02', 'field3': 'val03', 'field4': 'val04'},
      {'field1': 'val11', 'field2': 'val12', 'field3': 'val13', 'field4': 'val14'},
      {'field1': 'val21', 'field2': 'val22', 'field3': 'val23', 'field4': 'val24'},
      {'field1': 'val31', 'field2': 'val32', 'field3': 'val33', 'field4': 'val34'}
];

var fields13 = [];
var fields24 = [];


_.each(myarr, function(myobj) 
{ 
      fields13.push(myobj.field1);
      fields24.push(myobj.field2);
      fields13.push(myobj.field3);
      fields24.push(myobj.field4);
});

console.log(fields13);
console.log(fields24);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top