0

I have this array of objects that I retrieved from an API. It is continuously being updated everyday. The array consists of a timeseries of cases for everyday. I want to use this array to return the cases for each date for the last week. I have fetched the country name and filtered the array, so it only shows the user's country's array. I was thinking I can map across the dates of the array to find the last 7 indexes. Is there a way to do this?

useEffect(() => {
      axios
        .get("https://api.covid19india.org/v4/min/timeseries.min.json")
        .then((response) => {
          setEarliest2(response.data);

          const stateArray = response.data.filter(
            (item) => item.country === mappedLocation.stateShort
          );
}
{
  "AN": {
    "dates": {
      "2020-03-26": {
        "delta": {
          "confirmed": 1
        },
        "delta7": {
          "confirmed": 1
        },
        "total": {
          "confirmed": 1
        }
      },
      "2020-03-27": {
        "delta": {
          "confirmed": 5
        },
        "delta7": {
          "confirmed": 6
        },
        "total": {
          "confirmed": 6
        }
      },
      "2020-03-28": {
        "delta": {
          "confirmed": 3
        },
        "delta7": {
          "confirmed": 9
        },
        "total": {
          "confirmed": 9
        }
      },
      "2020-03-29": {
        "delta7": {
          "confirmed": 9
        },
        "total": {
          "confirmed": 9
        }
      },
      "2020-03-30": {
        "delta": {
          "confirmed": 1
        },
        "delta7": {
          "confirmed": 10
        },
        "total": {
          "confirmed": 10
        }
      },
  ...
}
const DataSet = (props) => {
return [
    {
      x: new Date(
        parseInt(moment().format("YYYY")),
        parseInt(moment().format("M")),
        parseInt(moment().format("DD")) - 7
      ),
5
  • 1
    There's no such thing as a JSON array. response.data is an array of objects. Commented May 26, 2021 at 18:02
  • 1
    And why is this tagged with typescript and react-native? Commented May 26, 2021 at 18:03
  • 1
    Grab the "dates" (Object.keys()), sort them, get the first/last (depending on the sort order) seven Commented May 26, 2021 at 18:04
  • @Andreas Yes, I meant to say an array of objects, but it is a JSON. It's tagged with them because I am building with react-native and typescript? Otherwise, why would I tag those? Could you provide an example of your answer? Commented May 26, 2021 at 18:10
  • 1
    Axios automatically parses the JSON to arrays and objects. If it was truly still JSON, it would be a string, and you'd get an error when you wrote response.data.filter since strings don't have a filter method. Commented May 26, 2021 at 19:34

2 Answers 2

2

Use Object.keys to get an array of dates, then sort it, slice it and get cases from the original response:

function getLast7DaysCases (response) {
  const cases = response.data['AN'].dates
  return Object.keys(cases)
    .sort()
    .reverse()
    .slice(0, 7)
    .reduce((acc, k) => ({ ...acc, [k]: cases[k] }), {})
}
Sign up to request clarification or add additional context in comments.

1 Comment

Instead of .sort().reverse() just .slice() from the end of the list with .slice(-7)
1

If you can use ES2019+:

const getPastCasesByCountry = (response, country, pastDays) => Object.fromEntries(
  Object.entries(response[country].dates)
    .sort(([date1], [date2]) => date1.localeCompare(date2))
    .slice(-pastDays)
);

const last7DaysAN = getPastCasesByCountry(response, 'AN', 7);

This uses

  • the handy Object.entries + Object.fromEntries combo which gives you the ability to work with an object essentialy the same way as with an array
  • the fact that Array.slice can take a negative start index, which is an offset from the end – as we needed here

Convert to data set

To convert to DataSet as described in your question, I'd change the function a bit:

const getPastCasesByCountry = (response, country, pastDays) => 
  Object.entries(response[country].dates)
    .sort(([date1], [date2]) => date1.localeCompare(date2))
    .slice(-pastDays)

const DataSet = (casesByDate) => casesByDate.map(([dateString, cases]) => ({
  x: new Date(dateString),
  y: cases.total.confirmed
}))

const data = DataSet(getPastCasesByCountry(response, 'AN', 7));

6 Comments

Thank you for this. Is there a way to return this array object, so I can use it in other files maybe using props and hooks?
An object is an unsorted collection of key-value pairs. Therefor this answer only works when the order of the properties ends in the correct order after parsing the response - which is not guaranteed.
@Andreas You're right, thanks for the catch! I just wanted to show an alternative to reduce (as in @denis-t's answer), but forgot about order 🤦‍♂️ I'll edit to reflect that.
@Andreas @ rsmeral thank you both for your insight on this. Do you have an answer to my question above?
What do you mean by "other files"? Like child components? And what do you mean by "this array object"? The object containing the past 7 days for a particular country?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.