简体   繁体   中英

javascript pattern matching object

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?

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); 

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) => oa === 1 ? r.concat(ob) : 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); 

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.

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]

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]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM