Как правильно отфильтровать объект, имеющий массив объектов - PullRequest
1 голос
/ 29 мая 2020

Я пытаюсь отфильтровать массив, чтобы получить только то, что хочу, и я пробовал использовать фильтр и уменьшить, но не смог заставить его полностью работать. Я пытаюсь получить только объекты, у которых есть "System.State" с "oldValue" и "newValue"

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

Проблема в том, что массив value содержит несколько объектов, которые могут НЕ иметь "System.State" и некоторые, у которых есть "System.State", но только с "newValue" вместо "oldValue" и "newValue", поэтому я получаю много неопределенных ошибок и действительно не знаю, как лечить эти ситуации.

Это пример, в котором нет "System.State" и еще один с "System.State ", но только с "newValue":

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"
        }
      }
    },
  ]
}

Я использую TFS API, если кто-то хочет знать . Это то, что я пробовал использовать с фильтром:

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

И это с использованием редуктора:

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

Что я делаю не так? Кстати, я использую ['System.State'] потому что я не могу получить доступ к свойству объекта с точкой.

Ответы [ 3 ]

2 голосов
/ 29 мая 2020

В вашем примере filter замените data.value.fields.filter() на data.value.filter(), потому что data.value - это массив.

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

);
1 голос
/ 29 мая 2020

Просто отфильтруйте свойство value, чтобы включить только те элементы массива, которые содержат:

"fields": {
  "System.State": {
    "oldValue": "anything",
    "newValue:": "anything"
  }
}

function filterData(data) {
  let filteredValue = data.value.filter(el => {
    return el.fields["System.State"] &&
      el.fields["System.State"].oldValue &&
      el.fields["System.State"].newValue;
  });
  return { value: filteredValue };
}

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"
        }
      }
    },
  ]
}

let filtData = filterData(data);
document.getElementById('results').innerHTML =
  JSON.stringify(filtData, null, 2);
Filtered data:
1 голос
/ 29 мая 2020

Это data.value.fields не определено, вы должны получить доступ к свойству fields через каждый объект в свойстве value.

const data = {  "value": [    {      "id": 23,      "fields": {        "System.State": {          "oldValue": "Forecasted",          "newValue": "Done"        }      }    },    {      "id": 24,      "fields": {        "System.State": {          "newValue": "New"        }      }    },    {      "id": 25,      "fields": {        "System.AuthorizedDate": {          "newValue": "2020-03-13T14:14:37.1Z"        }      }    }  ]};

console.log(data.value.filter(({fields: {"System.State": state}}) => {
  return state && state.oldValue === "Forecasted" && state.newValue === "Done";
}));
...