Swift函数在另一个函数中不起作用

时间:2018-06-19 19:15:02

标签: swift function

我是这个网站的新手,但是对于这个问题,我已经苦苦挣扎了好几天。我编写此代码是为了解决Codewars网站的挑战;挑战在于根据一些虚构降雨的一些数据计算均值和方差(我将完整页面附在底部)。为了解决这一难题,我创建了一个函数,用于将无用字符串中的数据转换为Doubles数组。奇怪的是,该函数如果在主函数外部调用,则可以正常工作,但在内部返回一个空数组。我不知道为什么会这样。非常感谢您为尝试向我解释这一点而付出的所有努力。

This is the first part of the Codewars page that explain the callenge

This is the second one

//
//  main.swift
//  Prova
//
//  Created by Lorenzo Santini on 13/06/18.
//  Copyright © 2018 Lorenzo Santini. All rights reserved.
//

import Foundation


func mean(_ d: String,_ town: String) -> Double {
    let arrayOfValues = obtainArrayOfMeasures(d, town)
    var sum: Double = 0
    for element in arrayOfValues {
        sum += element
    }

    return sum / Double(arrayOfValues.count)
}


func variance(_ d: String,_ town: String) -> Double {
    let meanValue: Double = mean(d, town)

    //Here is the problem: when this function is called instead of returning the array containg all the measures for the selected city it returns an empty array
    var arrayOfValues = obtainArrayOfMeasures(d, town)
    var sum: Double = 0
    for element in arrayOfValues {
        sum += pow((element - meanValue), 2)
    }
    return sum / Double(arrayOfValues.count)
}

func isInt(_ char: Character) -> Bool {
    switch char {
    case "1","2","3","4","5","6","7","8","9":
        return true
    default:
        return false
    }
}

func obtainArrayOfMeasures(_ d: String,_ town: String) -> [Double]{
    //The first array stores the Data string divided for city
    var arrayOfString: [String] = []
    //The second array stores the measures of rainfall of the town passed as argument for the function
    var arrayOfMeasures: [Double] = []

    //Split the d variable containg the data string in separated strings for each town and add it to the arrayOfString array
    repeat {
        let finalIndex = (data.index(of:"\n")) ?? data.endIndex
        arrayOfString.append(String(data[data.startIndex..<finalIndex]))
        let finalIndexToRemove = (data.endIndex == finalIndex) ? finalIndex : data.index(finalIndex, offsetBy: 1)
        data.removeSubrange(data.startIndex..<finalIndexToRemove)
    } while data.count != 0

    //Find the string of the town passed as argument
    var stringContainingTown: String? = nil
    for string in arrayOfString {
        if string.contains(town) {stringContainingTown = string; print("true")}
    }

    if stringContainingTown != nil {
        var stringNumber = ""
        var index = 0

        //Add to arrayOfMeasures the measures of the selected town
        for char in stringContainingTown! {
            index += 1
            if isInt(char) || char == "." {
                stringNumber += String(char)
                print(stringNumber)
            }
            if char == "," || index == stringContainingTown!.count {
                arrayOfMeasures.append((stringNumber as NSString).doubleValue)
                stringNumber = ""
            }
        }
    }

    return arrayOfMeasures
}




var data =  "Rome:Jan 81.2,Feb 63.2,Mar 70.3,Apr 55.7,May 53.0,Jun 36.4,Jul 17.5,Aug 27.5,Sep 60.9,Oct 117.7,Nov 111.0,Dec 97.9" + "\n" +
        "London:Jan 48.0,Feb 38.9,Mar 39.9,Apr 42.2,May 47.3,Jun 52.1,Jul 59.5,Aug 57.2,Sep 55.4,Oct 62.0,Nov 59.0,Dec 52.9" + "\n" +
        "Paris:Jan 182.3,Feb 120.6,Mar 158.1,Apr 204.9,May 323.1,Jun 300.5,Jul 236.8,Aug 192.9,Sep 66.3,Oct 63.3,Nov 83.2,Dec 154.7" + "\n" +
        "NY:Jan 108.7,Feb 101.8,Mar 131.9,Apr 93.5,May 98.8,Jun 93.6,Jul 102.2,Aug 131.8,Sep 92.0,Oct 82.3,Nov 107.8,Dec 94.2" + "\n" +
        "Vancouver:Jan 145.7,Feb 121.4,Mar 102.3,Apr 69.2,May 55.8,Jun 47.1,Jul 31.3,Aug 37.0,Sep 59.6,Oct 116.3,Nov 154.6,Dec 171.5" + "\n" +
        "Sydney:Jan 103.4,Feb 111.0,Mar 131.3,Apr 129.7,May 123.0,Jun 129.2,Jul 102.8,Aug 80.3,Sep 69.3,Oct 82.6,Nov 81.4,Dec 78.2" + "\n" +
        "Bangkok:Jan 10.6,Feb 28.2,Mar 30.7,Apr 71.8,May 189.4,Jun 151.7,Jul 158.2,Aug 187.0,Sep 319.9,Oct 230.8,Nov 57.3,Dec 9.4" + "\n" +
        "Tokyo:Jan 49.9,Feb 71.5,Mar 106.4,Apr 129.2,May 144.0,Jun 176.0,Jul 135.6,Aug 148.5,Sep 216.4,Oct 194.1,Nov 95.6,Dec 54.4" + "\n" +
        "Beijing:Jan 3.9,Feb 4.7,Mar 8.2,Apr 18.4,May 33.0,Jun 78.1,Jul 224.3,Aug 170.0,Sep 58.4,Oct 18.0,Nov 9.3,Dec 2.7" + "\n" +
"Lima:Jan 1.2,Feb 0.9,Mar 0.7,Apr 0.4,May 0.6,Jun 1.8,Jul 4.4,Aug 3.1,Sep 3.3,Oct 1.7,Nov 0.5,Dec 0.7"


var prova = variance(data, "London")

1 个答案:

答案 0 :(得分:2)

问题是func obtainArrayOfMeasures修改了全局data 变量。第二次调用时,data是一个空字符串。

该问题的一个指标是使全局数据变量恒定

let data =  "Rome:..."

在以下位置导致编译器错误

data.removeSubrange(data.startIndex..<finalIndexToRemove)
// Cannot use mutating member on immutable value: 'data' is a 'let' constant

一个直接的解决方法是对 local 可变副本进行操作:

func obtainArrayOfMeasures(_ d: String,_ town: String) -> [Double]{
    var data = d

    // ...
}

但是请注意,该功能可以简化为

func obtainArrayOfMeasures(_ d: String,_ town: String) -> [Double] {
    let lines = d.components(separatedBy: .newlines)

    guard let line = lines.first(where: { $0.hasPrefix(town)}) else {
        return [] // No matching line found.
    }
    let entries = line.components(separatedBy: ",")
    let numbers = entries.compactMap { Double($0.filter {".0123456789".contains($0) })}
    return numbers
}

,不更改任何值。您可能还考虑返回nil 或如果找不到匹配的条目,则用fatalError()中止。