8

Have array of currency rates and after input amount in inputTextField i'm want to update all items in this array on the amount in this currency and put that one in the tableView, tried to do that with loop but that's not working correct because that's solution just putted in the table each loop

inputTextField that's name of the text field

receivedRates:[Double] = [1.1,1.6,2.0,1.3] // just example of the rates

for i in receivedRates {

    let newValue = Double(i)*Double(Int(inputTextField.text!)!)
    currentAmount.append(newValue)
    receivedRates = currentAmount
}

How to update this array without loop or maybe there some other solution for this loop?

vadian
  • 274,689
  • 30
  • 353
  • 361
Ula
  • 167
  • 1
  • 2
  • 11

5 Answers5

16

You want to multply all items in the array with the double value of the text field.

A very suitable way in Swift is map

var receivedRates = [1.1, 1.6, 2.0, 1.3]

receivedRates = receivedRates.map{ $0 * Double(inputTextField.text!)! }

Alternatively you can enumerate the indices and update the values in place

receivedRates.indices.forEach{ receivedRates[$0] *= Double(inputTextField.text!)! }

I doubt that you really want to convert the text first to Int (losing the fractional part) and then to Double and of course you should unwrap the optionals safely.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • map is far much faster then for loop – dahiya_boy Jan 21 '18 at 09:54
  • I want to set them all to zero and it has this error message about "contextual type" and then inserts an underscore in the "fix". Edit: I solved it by specifying "$0 * 0". Kinda weird but okay – pete Aug 07 '20 at 09:01
6

You can also extend MutableCollection and implement your own mutable map method to transform your array:

extension MutableCollection {
    mutating func mutableMap(_ transform: (Element) throws -> Element) rethrows {
        var index = startIndex
        for element in self {
            self[index] = try transform(element)
            formIndex(after: &index)
        }
    }
}

Usage:

var receivedRates = [1.1, 1.6, 2.0, 1.3]
receivedRates.mutableMap { $0 * 2.5 }
print(receivedRates)    // [2.75, 4, 5, 3.25]

In your case:

if let value = Double(inputTextField.text!) {
    receivedRates.mutableMap { $0 * value }
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
1

You could use .map function

Loops over a collection and applies the same operation to each element in the collection.

receivedRates = receivedRates.map{ $0 * Double(inputTextField.text!)!}

Refer: Higher Order Functions

Lal Krishna
  • 15,485
  • 6
  • 64
  • 84
1
let newValue = Double(i)*Double(Int(inputTextField.text!)!)

The forced unwrappings (!) here is a warning flag, and something that is likely to break easily at runtime of your app.

As the text property of the inputTextField instance is an optional, you should make sure safely to unwrap it prior attempting to using it in an attempted initialization for a Double instance. Moreover, the same holds of the result of the attempted initialization (which is also an optional).

You could achieve this double safe unwrapping logic e.g. using optional binding and the flatMap(...) method of Optional; whereafter you may use e.g. map to update the values of the receivedRates array:

var receivedRates = [1.1, 1.6, 2.0, 1.3]

if let rateFactor = inputTextField.text.flatMap(Double.init) {
    receivedRates = receivedRates.map { $0 * rateFactor }
}

Or, element mutation in place (I see no reason why not to use a for .. in loop here):

if let rateFactor = inputTextField.text.flatMap(Double.init) {
    for idx in receivedRates.indices {
        receivedRates[idx] *= rateFactor
    }
}

Note that if either the text property is nil or if the initialization of a Double instance by it fails, then the array will not be updated (a case which could handle specifically in an else clause to the if statement above).

dfrib
  • 70,367
  • 12
  • 127
  • 192
0

Can use map instead of for-in loop, which is much faster, but you have to avoid the usage of force unwrapping optionals (!) as much as possible, for example as following:

func updateRates(_ receivedRates: inout [Double], by text: String?) -> Bool {
    guard text != nil, let inputValue = Double(text!) else { return false }

    receivedRates = receivedRates.map{ $0 * inputValue }
    return true
}

Usage:

    var receivedRates: [Double] = [1.1, 1.6, 2.0, 1.3]
    if updateRates(&receivedRates, by: inputTextField.text) {
        print(receivedRates)
    }

Another advantage is that you are using referenced parameters inout to update the original receivedRates array

AamirR
  • 11,672
  • 4
  • 59
  • 73