Home > Enterprise >  How to create a new list from two partial lists & based on one partial list?
How to create a new list from two partial lists & based on one partial list?

Time:11-02

This requires some genius, experience & knowledge I don't yet have in Dart, so I'm looking for help.

I am trying to populate a line chart, when users first begin using software there will be "empty" entries in the chart data. There also may be "zero" entries or no entry at all for some weeks or entries. I want to ensure that my line chart shows zero (for sales income - yAxis) for any missing entries based on a graph with 13 entries shown always.

For example mockupGraphData would be an existing situation where a couple sales dates are missing entries (based on weekly entries) and there are not enough entries to satisfy the graph appetite.

I would like to automatically enter "zeroed" dates. Where the date would be the index of missing date and GraphData.yAxis (income) would be zero.

Below does not compile of course, consider the last loop pseudo code of what I think would work if I could get around the index not existing in the mockupGraphData...

void main() {
  
  // Actual "mock" input data
  List<GraphData> mockupGraphData = [
    GraphData(1586761200000, 145333),
    GraphData(1587366000000, 433343),
    GraphData(1587970800000, 223432),
    GraphData(1589180400000, 122221),
    GraphData(1589785200000, 982347),
    GraphData(1590994800000, 234322),
  ];
  
  // Required graph dates as per below calculations (13 entries):
    // 1583737200000
    // 1584342000000
    // 1584946800000
    // 1585551600000
    // 1586156400000
    // 1586761200000
    // 1587366000000
    // 1587970800000
    // 1588575600000
    // 1589180400000
    // 1589785200000
    // 1590390000000
    // 1590994800000

  int entries = 13;
  int latestDateReported = DateTime(2020, 6, 1).millisecondsSinceEpoch;
  int oneWeek = Duration(days: 7).inMilliseconds;
  int earliestEntryDate = latestDateReported - (oneWeek * entries);
  List<int> graphRequiredDates = [];
  List<GraphData> finalData = [];
  
  for (int i = 0; i < entries; i  ) {
    earliestEntryDate  = oneWeek;
    graphRequiredDates.add(earliestEntryDate);
  }
  // What I would like to do
  for (int i = 0; i < entries; i  ) {
    if (!mockupGraphData.contains(GraphData(graphRequiredDates[i]))) {
      finalData.add(GraphData(graphRequiredDates[i], 0));
    }
  }
  
  print(finalData);
}

class GraphData {
    int xAxis; // Sale date
    int yAxis; // Sale income
  
  GraphData(this.xAxis, this.yAxis);
  
  @override
  String toString() {
    return '$xAxis $yAxis';
  }
  }
// IDEAL OUTPUT:
  List<GraphData> mockupGraphData = [
    GraphData(1583737200000, 0),
    GraphData(1584342000000, 0),
    GraphData(1584946800000, 0),
    GraphData(1585551600000, 0),
    GraphData(1586156400000, 0),
    GraphData(1586761200000, 145333),
    GraphData(1587366000000, 433343),
    GraphData(1587970800000, 223432),
    GraphData(1588575600000, 0),
    GraphData(1589180400000, 122221),
    GraphData(1589785200000, 982347),
    GraphData(1590390000000, 0),
    GraphData(1590994800000, 234322),
  ];

CodePudding user response:

Instead of storing mockupGraphData as a List<GraphData>, I would use a Map<int, int> that maps timestamps to values. From there, it's easy to iterate over your list of expected timestamps, check if a timestamp already exists in mockupGraphData, and then construct GraphData objects appropriately.

You additionally can use collection-for to make some of your code neater:

void main() {
  // Actual "mock" input data

  var mockupGraphData = <int, int>{
    1586761200000: 145333,
    1587366000000: 433343,
    1587970800000: 223432,
    1589180400000: 122221,
    1589785200000: 982347,
    1590994800000: 234322,
  };

  int entries = 13;
  int latestDateReported = DateTime(2020, 6, 1).millisecondsSinceEpoch;
  int oneWeek = Duration(days: 7).inMilliseconds;
  int earliestEntryDate = latestDateReported - (oneWeek * (entries - 1));
  List<int> graphRequiredDates = [
    for (var i = 0; i < entries; i  )
      earliestEntryDate   i * oneWeek,
  ];
  List<GraphData> finalData = [
    for (var requiredDate in graphRequiredDates)
      GraphData(requiredDate, mockupGraphData[requiredDate] ?? 0),
  ];

  finalData.forEach(print);
}

class GraphData {
  int xAxis; // Sale date
  int yAxis; // Sale income

  GraphData(this.xAxis, this.yAxis);

  @override
  String toString() {
    return 'GraphData($xAxis, $yAxis)';
  }
}

CodePudding user response:

You could try something like this:

void main() {
  List<GraphData> mockupGraphData = [
    GraphData(1586761200000, 145333),
    GraphData(1587366000000, 433343),
    GraphData(1587970800000, 223432),
    GraphData(1589180400000, 122221),
    GraphData(1589785200000, 982347),
    GraphData(1590994800000, 234322),
  ];

  int entries = 13;
  int latestDateReported = DateTime(2020, 6, 1).millisecondsSinceEpoch;
  int oneWeek = Duration(days: 7).inMilliseconds;
  int earliestEntryDate = 1583737200000;

  final result = [
    for (int i = 0, v = 0; i < entries; i  , earliestEntryDate  = oneWeek)
      if (mockupGraphData[v].xAxis == earliestEntryDate)
        mockupGraphData[v  ]
      else
        GraphData(earliestEntryDate, 0),
  ];

  result.forEach(print);
}

class GraphData {
  int xAxis; // Sale date
  int yAxis; // Sale income

  GraphData(this.xAxis, this.yAxis);

  @override
  String toString() {
    return '$xAxis $yAxis';
  }
}

I hardcoded the value of earliestEntryDate since the calculation didn't seem to match with the expected output. The above solution assumes mockupGraphData is in sorted order, and that the values are at least a week apart.

  • Related