Отметить закрывающий элемент изменяемым Swift

#swift

#swift

Вопрос:

У меня есть 2 структуры, первая из которых:

 struct LineData {

    init (name: String,
          colorValue: String,
          values: [Int]){
        self.name = name
        self.colorValue = colorValue
        self.values = values
    }

    private var cachedMaxValue: Int? = nil
    let name: String
    let colorValue: String
    let values: [Int]

    // describe max value for Y axis for specific Line
    mutating func maxValue() -> Int{
        if let cached = cachedMaxValue {
            return cached
        }
        self.cachedMaxValue = values.max()
        return cachedMaxValue ?? 0
    }
}
  

У второго есть массив LineData структур:

 struct CharData {

    init(xAxis: XAxis,
         lines: [LineData]){
        self.xAxis = xAxis
        self.lines = lines
    }

    private var cachedMaxValue: Int? = nil

    var xAxis: XAxis
    var lines: [LineData]

    // describe max value for Y axis among lines
    func maxValue() -> Int{

        var maxValues: [Int] = []
        lines.forEach{it in
            maxValues.append(it.maxValue())
        }

        return 0
    }
}
  

Приведенный выше код не компилируется из-за ошибки в методе maxValues для struct CharData . В нем говорится Cannot use mutating member on immutable value: 'it' is a 'let' constant

Что я хочу, так это выполнить итерацию по массиву строк и среди его максимальных значений найти большее значение.

Ответ №1:

Поскольку lines — это обычный массив, как насчет простого:

     for i in 0..<lines.count {
        maxValues.append(lines[i].maxValue())
    }
  

возможно, не так быстро, но ничего не копируется. Оптимизатор должен обеспечить вам практически такую же производительность, как у forEach.

Комментарии:

1. for i in lines.indices {

Ответ №2:

Неизменяемым является it параметр / объект в forEach. Точно так же, как написано в ошибке: «это let». Вероятно, вы могли бы сделать что-то вроде этого:

 lines.forEach { it in
    var mutableIt = it
    maxValues.append(mutableIt.maxValue())
}
  

Следует отметить, что это создаст изменяемую копию экземпляра структуры «it».

Комментарии:

1. Однако это не соответствовало бы цели кэширования. cachedMaxValue обновляется только во (временной) изменяемой копии.

2. @EvgeniyKleban Конечно, создание всех этих копий может привести к снижению производительности при работе с большими наборами данных (я предполагаю, что именно поэтому вы кэшируете значение в первую очередь). Возможно, вам было бы лучше использовать другой стиль for цикла вместо этого.

3. @MartinR Вы абсолютно правы. Это решает исходную проблему, но с большими наборами данных могут возникнуть проблемы, связанные с производительностью. Я полагаю, зависит от конкретного варианта использования.