Select a property from an array of objects based on a value : Javascript

73,401

Solution 1

You can use reduce and check if the checked property is true, then push (As pointed out by assoron) the value to the accumulator - there is no need for 2 loops:

const arr = [
  { "value": "abc", "checked": true },
  { "value": "xyz", "checked": false },
  { "value": "lmn", "checked": true }
]

const filtered = arr.reduce((a, o) => (o.checked && a.push(o.value), a), [])      
console.log(filtered)

Solution 2

use filter and map:

const arr =[{"value":"abc","checked":true},{"value":"xyz","checked":false},{"value":"lmn","checked":true}];

 const result = arr.filter(res=>res.checked).map(ele=>ele.value);
 
 console.log(result);

Solution 3

Firstly, that's not valid JS - you need to swap your brackets and braces. Arrays use [], and objects use {}, not the other way around.

Secondly, you should first filter out the wanted objects based on the checked property, then use map to extract the properties you want:

const arr =[{"value":"abc","checked":true},{"value":"xyz","checked":false},{"value":"lmn","checked":true}];

const res = arr.filter(({ checked }) => checked).map(({ value }) => value);

console.log(res);

Solution 4

You can use .reduce to essentially map and filter at the same time. Below I have built an accumulated array using [v].slice(+!c) which will add the value to the (accumulated) array if c is true, else, it will not add it to the array (as [v].slice(+!false) will return [], and [...[]] will give []):

const arr = [{
 "value": "abc",
 "checked": true
}, {
 "value": "xyz",
 "checked": false
}, {
 "value": "lmn",
 "checked": true
}];

const res = arr.reduce((a, {value:v, checked:c}) => [...a, ...[v].slice(+!c)], []);
console.log(res);

Solution 5

Array.prototype.reduce() might help you. reduce() callback takes two arguments, who's first argument is the old/previous iteration value and second argument is the current iteration value/element.

So using this function we can holds our current iteration values to the previous iteration value (total values).

The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.

var arr = [{"value": "abc","checked": true},{"value": "xyz","checked": false},{"value": "lmn","checked": true}]

const result = arr.reduce((acc, cur) => ((cur.checked && acc.push(cur.value)), acc), [])
console.log(result)
Share:
73,401

Related videos on Youtube

joy08
Author by

joy08

Updated on June 09, 2020

Comments

  • joy08
    joy08 almost 4 years

    I have an array of objects with the following structure:

    var arr = [
      {
        "value": "abc",
        "checked": true
      },
      {
        "value": "xyz",
        "checked": false
      },
      {
        "value": "lmn",
        "checked": true
      }
    ];
    
    let result = arr.filter(item => item.checked);
    
    console.log(result);

    I would want the output to be:

    ["abc", "lmn"] 
    

    Because those two values have checked: true.

    I have tried filtering out based on checked value:

    let result = arr.filter(item => item.checked);
    

    I am getting the objects that has checked property value that is set to true.

    Help would be appreciated.

    • CertainPerformance
      CertainPerformance almost 5 years
      Your input's syntax is invalid. Consider providing a valid data structure. Arrays do not have key-value pairs, only values
    • Matsemann
      Matsemann almost 5 years
  • MH2K9
    MH2K9 almost 5 years
    only returns the last one of (...)
  • Kobe
    Kobe almost 5 years
    Thats why I used reduce :) Nonetheless, a for loop is more efficient here.
  • Rajaprabhu Aravindasamy
    Rajaprabhu Aravindasamy almost 5 years
    @Kobe Agree...!
  • claasic
    claasic almost 5 years
    Faster than all the filter plus map answers for sure. But why use concat for this? Wouldn't {if (c.checked) {a.push(c.value) }; return a} be more efficient? Spread syntax afaik is kinda slower so that might be a third but likely worse option anyway.
  • Kobe
    Kobe almost 5 years
    @assoron Yes, you are right. I only wrote concat so you could write it on one line so as to be more readable. And spread syntax is horribly slower, I remember writing a JSPerf once and iirc it was 50% slower.
  • Kobe
    Kobe almost 5 years
    @assoron check this perf jsperf.com/push-vs-concat-with-reduce/1 - 94% slower lol
  • claasic
    claasic almost 5 years
    My ancient browser setup puts concat as 40% slower.
  • Jack Bashford
    Jack Bashford almost 5 years
    You can do it in one line with push: (a.push(o.value), a).
  • Kobe
    Kobe almost 5 years
    @JackBashford I never knew this existed, thanks, that will help for a lot more one liners with efficiency too :P
  • Jack Bashford
    Jack Bashford almost 5 years
    No worries - I (ab)use the comma operator like that in a lot of my reduce answers now.
  • Kobe
    Kobe almost 5 years
    @JackBashford Are you able to explain how it works?
  • Jack Bashford
    Jack Bashford almost 5 years
    Yep - the comma operator evaluates all code passed, then uses the last one. So a.push(o.value) is run, then a is used as the return value of the expression, and returned from the function. Make sense?
  • Kobe
    Kobe almost 5 years
    How come you are using old syntax here? It looks odd on one line when it's not es6 :P
  • SK.
    SK. almost 3 years
    if you want unique values: const result = Array.from(new Set(arr.filter(res=>res.checked).map(ele=>ele.value)));