random dreamer
random dreamer

Reputation: 237

filtring boolean values inside an array of objects

I have an array like this :

 const appoint =[
  { a: "asas",
    b:{au: false, h:false,l:true}
  },
  { a: "avd",
    b:{au: true, h:false,l:true}
  },
  { a: "as", b:{au: true, h:false,l:false}
  }];

When I access b , I want to filter the falsy values, so far I'm not successful doing it with a serie of map() like this :

const result = appoint.map(elem => elem.b.)
const finalresult = result.map(
         item =>item.filter(
              (item, value)=> item[value] === false )
          )

Upvotes: 1

Views: 1205

Answers (4)

Sagar Khan
Sagar Khan

Reputation: 302

You can do something like this

let array = [{
    a: "asas",
    b: {
        au: false,
        h: false,
        l: true
    }
}, {
    a: "avd",
    b: {
        au: true,
        h: false,
        l: true
    }
}, {
    a: "as",
    b: {
        au: true,
        h: false,
        l: false
    }
}, {
    a: "ab",
    b: {
        au: false,
        h: false,
        l: false
    }
}]

let output = array.filter((element) => {
    let keys = Object.keys(element.b)
    element.b = keys.filter((key) => {
        if (element.b[key]) {
            return key
        }
    })
    if (!Object.keys(element.b).length) {
        element.b = []
    }
    return element;
})
console.log(output)   

This will give you

[
    {
        "a": "asas",
        "b": [
            "l"
        ]
    },
    {
        "a": "avd",
        "b": [
            "au",
            "l"
        ]
    },
    {
        "a": "as",
        "b": [
            "au"
        ]
    },
    {
        "a": "ab",
        "b": []
    }
]

I assume you might need an empty array if none of the values are true.

Upvotes: 0

Ori Drori
Ori Drori

Reputation: 192507

You can create a getKeysBy() function that takes an object, and a predicate and returns the keys that pass the predicate check.

Now you can use Array.flatMap() with getKeysBy() to get an array of all the keys.

const appoint = [{"a":"asas","b":{"au":false,"h":false,"l":true}},{"a":"avd","b":{"au":true,"h":false,"l":true}},{"a":"as","b":{"au":true,"h":false,"l":false}}]
  
const getKeysBy = (predicate, obj) => 
  Object.entries(obj)
  .filter(([, v]) => predicate(v))
  .map(([k]) => k)
  
const result = appoint.flatMap(o => getKeysBy(v => v !== false, o.b))

console.log(result)

Upvotes: 1

brk
brk

Reputation: 50326

You can first use map to get an new array which contains only b, then use reduce and inside reduce callback use for..in to iterate the object and get the keys which is true

const appoint = [{
    a: "asas",
    b: {
      au: false,
      h: false,
      l: true
    }
  },
  {
    a: "avd",
    b: {
      au: true,
      h: false,
      l: true
    }
  },
  {
    a: "as",
    b: {
      au: true,
      h: false,
      l: false
    }
  }
];


let filtered = appoint.map(function(item) {
  return item.b;
}).reduce(function(acc, curr) {
  for (let keys in curr) {
    if (curr[keys]) {
      acc.push(keys)
    }
  }

  return acc;
}, []);
console.log(filtered)

Upvotes: 1

dbramwell
dbramwell

Reputation: 1326

elem.b is an object, not an array, so you can't use filter on it. You could do something like this:

const bArray = appoint.map(elem => elem.b)
const finalresult = bArray.map(b => {
  bKeys = Object.keys(b)
  const filtered = {}
  bKeys.forEach(key => {
    if (!b[key]) filtered[key] = false
  })
  return filtered
})

Upvotes: 1

Related Questions