0

The answer I found is with one level of struct. In my code I want to find out how many same dates is in inside of the struct of the struct. I never use equatable before so I'm not sure how to implement it with struct inside struct.

I'm using Charts pod and the array chartMetricItemSets contains different readings with multiples days. ex: ["name": sugar, [["date": "Oct 10", "value": 120], ["date": "Oct 10", "value": 121], ["date": "Oct 11", "value": 120], ["date": "Oct 13", "value": 120], ["date": "Oct 13", "value": 121]]. The xAxisDates will be ["Oct 10", "Oct 11", "Oct 13"]

the x is the date and the y is for the same date sums

Goal: chartDataEntries should append [x:0(10/10), y:241], [x:1(10/11), y:120], [x:2(10/13), y: 241]

Thank you!

struct ChartData {
   let name: String
   let value: [ChartValue]
}

struct ChartValue {
    let date: Date
    let value: Double
 }

var chartMetricItemSets = [[ChartData]]()
var xAxisDates = [String]() //date array

func getChartDataSets() {
    for (index, chartHealthItemSet) in chartMetricItemSets.enumerated() {
        let dataSourceSelected = dataSourcesSelected[index]
        var chartDataEntries = [ChartDataEntry]() //array display on graph
        var chartYaxis: Double = 0
        var datePoint: Int = 0
        var countChartYaxis = 0
        var duplicateDateCount = 0

        for (index, item) in chartHealthItemSet[0].value.enumerated() {
            for (dateIndex, date) in xAxisDates.enumerated() {
                if item.date.convertDateToString(dateFormat: .monthDay) == date {
                    chartYaxis += item.value
                    datePoint = dateIndex
                    chartYaxis += 1
                    break
                }

                //missing counting duplicateDateCount 

                if duplicateDateCount == countChartYaxis {
                    chartDataEntries.append(ChartDataEntry(x: Double(datePoint), y: chartYaxis.roundUpNDecimal(n: 2)))
                }
            }
            print("chartYaxis: \(chartYaxis)")
            print("chartDataEntries: \(chartDataEntries)")
        }
        chartDataEntries.sort(by: { $0.x < $1.x })

        let set = LineChartDataSet(entries: chartDataEntries,
                                   label: HEALTH_TABLE.allCases[dataSourceSelected].info.name)

        set.mode = .linear // cubic line effect (smoother)
        set.colors = [HEALTH_TABLE.allCases[dataSourceSelected].info.chartColor]
        set.setCircleColor(.black)
        set.lineWidth = 1.5
        set.circleRadius = 3
        set.drawCircleHoleEnabled = false
        set.drawCirclesEnabled = true
        set.drawHorizontalHighlightIndicatorEnabled = true

        lineChartData?.addDataSet(set)
    }

    chartView.xAxis.valueFormatter = IndexAxisValueFormatter(values: xAxisDates)
    chartView.xAxis.granularity = 1
    chartView.xAxis.axisMinLabels = 4
    chartView.xAxis.axisMaxLabels = 6

    DispatchQueue.main.async {
        self.chartView.data = self.lineChartData
    }
}

1 Answer 1

1

In Swift 4 a useful API was introduced to group arrays to dictionaries by an arbitrary predicate.

You can group chartHealthItemSet[0]

let grouped = Dictionary(grouping: chartHealthItemSet[0], by: {$0.date.convertDateToString(dateFormat: .monthDay)}

The result is ["10/10":[ChartData], "10/11":[ChartData], ...]

Sort the keys and assign them to xAxisDates

xAxisDates = grouped.keys.sorted()

To get the sum of the values get the array from the grouped dictionary for the date key, map it to the values and sum them up

for (index, date) in xAxisDates.enumerated() {
    let sum = grouped[date]!.map{$0.value}.reduce{0.0, +}
    chartDataEntries.append(ChartDataEntry(x: Double(index), y: sum.roundUpNDecimal(n: 2)))
}
Sign up to request clarification or add additional context in comments.

2 Comments

Hi! Thank you for answering but I got "Type of expression is ambiguous without more context" error when I type out the first line. let grouped = ....
I got it! After changing a little bit :) Thank you so much!!

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.