Search code examples
javascriptecmascript-6tfs-sdk

How to properly filter an object that has an array of objects


I'm trying to filter an array to get only what I want and I have tried with filter and reduce, but I was not able to make it fully work. I'm trying to get only the objects that has "System.State" with an "oldValue" and a "newValue"

const data = {
  "value": [
    {
      "id": 23,
      "fields": {
        "System.State": {
          "oldValue": "Forecasted",
          "newValue": "Done"
        }
      }
    },
  ]
}

The problem is that value array contains several objects that may NOT have "System.State" and some that have "System.State" but only with "newValue", instead of "oldValue" and "newValue", so I'm receiving a lot of undefined errors and I really don't know how to treat these situations.

This is a example that dont have "System.State" and another one that have "System.State" but with "newValue" only:

const data = {
  "value": [
    {
      "id": 23,
      "fields": {
        "System.State": {
          "oldValue": "Forecasted",
          "newValue": "Done"
        }
      }
    },
    {
      "id": 24,
      "fields": {
        "System.State": {
          "newValue": "New"
        }
      }
    },
    {
      "id": 25,
      "fields": {
        "System.AuthorizedDate": { // This is only an example of an object that does not have System.State
          "newValue": "2020-03-13T14:14:37.1Z"
        }
      }
    },
  ]
}

I'm using TFS API if anyone wants to know. This is what I have tried using filter:

data.value.fields.filter(status => status.fields['System.State'].oldValue === 'Forecasted' && status.fields['System.State'] === 'Done')

And this was using reducer:

  const filter = data.value.reduce((c, n) => {
    const HasNewAndOldValue = c.fields['System.State'].oldValue === 'Forecasted' && c.fields['System.State'].newValue === 'Done';
    if (c.fields['System.State'] && HasNewAndOldValue) {
      return c;
    }
    c.push(n); 
  }, [])
  console.log(data.value.fields && filter);

What I'm doing wrong? Btw, I'm using ['System.State'] because I can't access an object property that has a dot.


Solution

  • In your filter example, replace data.value.fields.filter() with data.value.filter(), because data.value is an array.

    const data = {
      "value": [
        {
          "id": 23,
          "fields": {
            "System.State": {
              "oldValue": "Forecasted",
              "newValue": "Done"
            }
          }
        },
        {
          "id": 24,
          "fields": {
            "System.State": {
              "newValue": "New"
            }
          }
        },
        {
          "id": 25,
          "fields": {
            "System.AuthorizedDate": { // This is only an example of an object that does not have System.State
              "newValue": "2020-03-13T14:14:37.1Z"
            }
          }
        },
      ]
    }
    
    console.log(
      data.value.filter((item) => {
        const fields = item.fields || {};
        const state = fields['System.State'];
        if (!state) {
          return false;
        }
    
        return state.oldValue && state.newValue;
      })
    
    );