user6624961
user6624961

Reputation:

Textfield as input in average function

I recently wanted to code an Average-Calculator. My plan was to build a UITextField in which you can type Numbers separated by commas... By pressing the 'Calculate' button the App should calculate the Average of the Numbers above and give them out by setting a labeltext to the average. So I wrote my average function and received this error message:

Can not convert value of type 'UITextField' to expected element type 'Double'.

This is my Code:

@IBOutlet var Input: UITextField!
@IBOutlet var Output: UILabel!
@IBAction func Calculate(sender: AnyObject) {

    var grades:[Double] = [Input]
    func average(nums: [Double]) -> Double {

        var total = 0.0
        for grade in nums{

            total += Double(grade)
        }

        let gradesTotal = Double(nums.count)
        let average = total/gradesTotal
        return average
    }

    let Average = average(grades)

    Output.text = "Average: \(Average)"
}

Can you help me with my idea? Is there a better way to get an input?

Upvotes: 0

Views: 227

Answers (5)

user6624961
user6624961

Reputation:

Here is the complete code if someone is interested :)

@IBOutlet var input: UITextField!
@IBOutlet var output: UILabel!
@IBAction func calculate(sender: AnyObject) {

    var grades: [Double] = (input.text ?? "").componentsSeparatedByString(",").flatMap{
        Double($0.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()))
    }
    func average(nums: [Double]) -> Double? {

        var total = 0.0
        for grade in nums{

            total += Double(grade)
        }

        let gradesTotal = Double(nums.count)
        if gradesTotal > 0 {
            let average = total/gradesTotal
            return average
        } else {
            return nil
        }
    }

    if let averageValue = average(grades) {
        output.text = "Average: \(averageValue)"
    } else {
        output.text = "Average not available"
    }

}

@IBAction func userTappedCalculate(sender: AnyObject) { view.endEditing(true)
}

I added the line @IBAction func userTappedCalculate(sender: AnyObject) { view.endEditing(true) } to close the input TextField when you tap calculate...

Upvotes: 0

Raj Aggrawal
Raj Aggrawal

Reputation: 761

let textInput = txtInputView.text;
let components = textInput.componentsSeparatedByString(",");
let sum = 0.0;
for txt in components
{
     sum = sum + Double(txt);
}

let avg = sum / components.count;
print(avg)

Upvotes: 0

OOPer
OOPer

Reputation: 47896

Please use lower camel case for variables...

In this line:

var grades:[Double] = [Input]

Input is an instance of UITextField, so you are trying to assign a single-element Array<UITextField> to Array<Double>. You see you cannot do such sort of things.

If you want to accept a text which contains Numbers separated by commas, you need to explicitly convert the text to [Double].

To simplify, let's just ignore the nil or non-numeric values. Then you need to change your code as:

@IBOutlet var input: UITextField!
@IBOutlet var output: UILabel!
@IBAction func calculate(sender: AnyObject) {

    var grades: [Double] = (input.text ?? "").componentsSeparatedByString(",").flatMap{Double($0)}
    func average(nums: [Double]) -> Double {

        var total = 0.0
        for grade in nums{

            total += Double(grade)
        }

        let gradesTotal = Double(nums.count)
        let average = total/gradesTotal
        return average
    }

    let averageValue = average(grades)

    output.text = "Average: \(averageValue)"
}

The basic idea of this line:

var grades: [Double] = (input.text ?? "").componentsSeparatedByString(",").flatMap{Double($0)}

is well-described in Lu_'s answer. Mine is just a little safer version.


(Addition) Some explanation about safety:

UITextFields property text is of type String?, so you should think it can be nil. Giving a default value for nil with ?? operator.

And using Double($0)! may crash your app, as Double($0) will return nil for non-numeric strings.

Writing these reminded me one more crash case.

When gradesTotal == 0, the code above will crash with division by zero.

(The default value does not work well for "safety" in the code above...)

So, one more step ahead to safety:

@IBAction func calculate(sender: AnyObject) {

    var grades: [Double] = (input.text ?? "").componentsSeparatedByString(",").flatMap{
        Double($0.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()))
    }
    func average(nums: [Double]) -> Double? {

        var total = 0.0
        for grade in nums{

            total += Double(grade)
        }

        let gradesTotal = Double(nums.count)
        if gradesTotal > 0 {
        let average = total/gradesTotal
            return average
        } else {
            return nil
        }
    }

    if let averageValue = average(grades) {
        output.text = "Average: \(averageValue)"
    } else {
        output.text = "Average not available"
    }
}

Upvotes: 2

Lu_
Lu_

Reputation: 2685

You need to separate numbers to get that array if you do that: enter image description here

you can pass "doubles" array to your average function

code to copypaste :)

var str = "1,2,3,4,5,6"

let stringsWithNumbers = str.componentsSeparatedByString(",")

let doubles = stringsWithNumbers.map { Double($0)! }

Upvotes: 6

AnthoPak
AnthoPak

Reputation: 4391

What you have to do is using Double(Input.text) instead of [Input]. Right now, you were trying to convert a UITextField to a double, which causes the error.

Upvotes: 0

Related Questions