3

I have a typescript POJO as follows

  export interface Items {
        firstName?: String;
        lastname?: String;
        Address?: String;
        phoneNumber?: number;
        city?: String;
        state?: String;
        zipcode?: number;
        accountId?: number;
        status?: String;
        approvalStatus?: String;
        txId?: number;
        rxId?: number;
        txBankname?: String;
        rxBankName?: String;
        txCcy?: String;
        rxCcy?: String;
        txCcyAmt?:number;
        rxCcyAmt?:number;
         txDate?:date;
         rxDate?:date;
     }

In my html file, I have a form with all the fields from above POJO. When a user selects a field, the pojo gets populated with the text entered.

However the user can choose to remain many fields empty and their properties in the object would be null.

So on submit button click, when I check the POJO, it is as in the below screeshot.

An Example POJO

I want to populate another array with only the populated values ( not the null value properties ) .

  this.anotherArray = [ {name:firstName, value:"Andy"},{name:lastName, value:"Smith"}]

I need to use it for an ngFor List to display angular material chip

How do we do it in a very optimized way.

edit: My question is regarding checking null properties in object and the duplicate question reference is to an array. Even the answers have different approaches. The Approach to my question is using Object.entries while the duplicate reference has an approach of using map and Object.keys

prabhat gundepalli
  • 907
  • 3
  • 15
  • 39
  • 4
    Possible duplicate of [Javascript filter null object properties](https://stackoverflow.com/questions/41828787/javascript-filter-null-object-properties) – Brandon Taylor Jul 13 '18 at 15:21

3 Answers3

13

You can use Object.entries() to get name-value pairs, then map them to objects:

Object.entries(obj)
    .filter(([name, value]) => value !== null)
    .map(([name, value]) => ({name, value}));
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 1
    Easy to read and since it's using native methods, should be well optimized. +1 – Kokozaurus Jul 13 '18 at 15:24
  • Thanks. I felt this was the most optimized appraoch among the answers here. – prabhat gundepalli Jul 13 '18 at 17:06
  • @prabhatgundepalli I thought that the fact that my answer was doing a single full iteration of object's properties should mean that it was more optimal. I was wrong. BTW, I've provided an additional approach using just `reduce` too and it outperforms this answer by more than 20% in my AMD Athlon II X3 450, Firefox 61 and Linux Mint 18.3. – Matías Fidemraizer Jul 15 '18 at 14:38
  • @prabhatgundepalli https://jsperf.com/object-entries-filter-map-vs-reduce – Matías Fidemraizer Jul 15 '18 at 14:39
3

You can simply use Object.entries() and Array.reduce()

var fields = {
  "name":"andy",
  "age" : null,
  "email" : null,
  "status" : true
};

var result = Object.entries(fields).reduce((a,[key,val])=>{
  if(val)
    a.push({name : key, value : val});
  return a;
},[]);

console.log(result);

Output:

[
  {
    "name": "name",
    "value": "andy"
  },
  {
    "name": "status",
    "value": true
  }
]
amrender singh
  • 7,949
  • 3
  • 22
  • 28
2

One possible approach:

const obj = { a: 1, b: null, c: 2, d: null }

const output = Object.entries (obj)
                     .reduce ((a, [k, v]) => v !== null ? [...a, [k, v]] : a, [])
      
console.log(output)

Same approach with local mutation

Here's the same approach using local mutation of Array#reduce accmulator, which is more optimal.

Since Array#reduce receives an already allocated array with N empty slots (where N is the total number of keys in the input object), the array never requires an internal operation to increase its length. Once the object's entries are reduced, we filter out undefined items (those that were null):

const obj = {
  a: 1,
  b: null,
  c: 2,
  d: null
}

const keyCount = Object.keys(obj).length

const output = Object.entries(obj)
  .reduce((a, kvp, i) => {
    if (kvp[1] !== null) a[i] = kvp
    return a
  }, Array(keyCount))
  .filter(kvp => kvp)

console.log(output)

JSPerf perf test filter+map vs reduce+filter

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206