0

Given a javascript object array eg.

let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}]

is there a faster way of getting all the b values from each object which meet a specific criteria such as a = 1 to return something like

b_consolidated = [2,3]

instead of looping through every object in the array?

Stanley
  • 2,798
  • 5
  • 22
  • 44

5 Answers5

4

You can use Array#filter function to get the items of your criteria, then use Array#map to get only b property.

let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}];

let values = objArray.filter(item => item.a === 1).map(item => item.b);

console.log(values);

Or you can do this in one loop

let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}];
let values = [];

objArray.forEach(item => {

  if(item.a === 1) {
      values.push(item.b);
  }
  
});

console.log(values);
Suren Srapyan
  • 66,568
  • 14
  • 114
  • 112
  • 1
    Note for the question: You are still looping through every object implicitly with `filter` and `map`. I do not think it is possible to solve the question in a way that doesn't involve looping at some point. – Freeman Lambda May 15 '17 at 07:20
  • Looping twice, even. – Cerbrus May 15 '17 at 07:23
  • 1
    And why? Only for returning item? – Suren Srapyan May 15 '17 at 07:43
  • Filter is meant to be used when you want to _filter_ an array. What you're doing here is iterating over _all_ values of an array, then using only certain values. A `forEach` would be correct, there. – Cerbrus May 15 '17 at 07:44
3

You could use Array#reduce in a single loop.

let array = [{ a: 1, b: 2, c: 3}, { a: 1, b: 3, c: 2 }, { a: 2, b: 5, c: 1 }],
    result = array.reduce((r, o) => o.a === 1 ? r.concat(o.b) : r, []);

console.log(result);

Fastest version with for loop.

let array = [{ a: 1, b: 2, c: 3}, { a: 1, b: 3, c: 2 }, { a: 2, b: 5, c: 1 }],
    i, l,
    result = [];

for (i = 0, l = array.length; i < l; i++) {
    if (array[i].a === 1) {
        result.push(array[i].b);
    }
}

console.log(result);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • If you're concerned about performance, this `concat` approach is [rather slow](https://jsperf.com/reduce-concat-push) – Cerbrus May 15 '17 at 07:33
  • 2
    @Cerbrus, for a real speedy version, i would use a for loop, instead of some array prototypes for iterating. – Nina Scholz May 15 '17 at 07:35
1

You only need to iterate over the array once, if you use reduce:

let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}]

let result = objArray.reduce((arr, val) => {
  if(val.a === 1)
    arr.push(val.b);
  return arr;
}, []);

console.log(result);

This is as fast as it'll get, short of a manual for loop:

let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}]

let result = [];

for(var i = 0 ; i < objArray.length; i++){
  if(objArray[i].a === 1)
    result.push(objArray[i].b);
}

console.log(result);

Here's a JSPerf to illustrate the difference.
A manual for loop is by far the fastest.

Cerbrus
  • 70,800
  • 18
  • 132
  • 147
1

More faster would be using .reduce

let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}];

objArray.reduce(function(res,obj){
   if(obj.a===1)
     res.push(obj.b);
   return res;
},[]);

// [2,3]
Jagdish Idhate
  • 7,513
  • 9
  • 35
  • 51
  • 1
    Instead of `==`, [preferably](http://stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons) use `===`. – Cerbrus May 15 '17 at 07:34
-1

In Ramda

let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}]

R.pipe(
  R.filter(R.propEq('a', 1)),
  R.pluck('b')
)(objArray)

// [2, 3]
  • Filter returns the array values matched by the condition.
  • Pluck returns a new list by plucking the same named property off all objects in the list supplied.

Edit 1:

Example of using the mentioned reduce pattern in Ramda:

R.reduce((acc, x) => R.ifElse(
  R.propEq('a', 1), 
  (item) => R.pipe(R.prop('b'), R.append(R.__, acc))(item), 
  R.always(acc)
)(x), [])(objArray)

// [2, 3]
elpddev
  • 4,314
  • 4
  • 26
  • 47
  • 1
    So, in a question where the OP asks for fast code, you're: 1: loading a new library. 2: iterating over the array (at least) twice... – Cerbrus May 15 '17 at 07:28