问题
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?
回答1:
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.
回答2:
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 }
}
回答3:
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
回答4:
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).
回答5:
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
来源:https://stackoverflow.com/questions/48365504/how-to-update-all-items-in-array-in-the-correct-way