Swift - Convert values in array to doubles or floats - ios

I have an array with values which are strings (but all the strings are values like 1.0, 2.0, etc). I'm trying to convert those strings into doubles or floats so I can add them all together. How do I do this in swift?

let x = ["1.0", "1.5", "2.0"]
print(x.map {Double($0)!})

update: Xcode 8.3.2 • Swift 3.1
extension Collection where Iterator.Element == String {
var doubleArray: [Double] {
return flatMap{ Double($0) }
}
var floatArray: [Float] {
return flatMap{ Float($0) }
}
}
usage:
let strNumbersArray = ["1.5","2.3","3.7","4.5"] // ["1.5", "2.3", "3.7", "4.5"]
let doublesArray = strNumbersArray.doubleArray // [1.5, 2.3, 3.7, 4.5]
let floatsArray = strNumbersArray.floatArray // [1.5, 2.3, 3.7, 4.5]
let total = doublesArray.reduce(0, +) // 12
let average = total / Double(doublesArray.count) // 3
If you have an Array of Any? where you need to convert all strings from Optional Any to Double:
extension Collection where Iterator.Element == Any? {
var doubleArrayFromStrings: [Double] {
return flatMap{ Double($0 as? String ?? "") }
}
var floatArrayFromStrings: [Float] {
return flatMap{ Float($0 as? String ?? "") }
}
}
usage:
let strNumbersArray:[Any?] = ["1.5","2.3","3.7","4.5", nil] // [{Some "1.5"}, {Some "2.3"}, {Some "3.7"}, {Some "4.5"}, nil]
let doublesArray = strNumbersArray.doubleArrayFromStrings // [1.5, 2.3, 3.7, 4.5]
let floatsArray = strNumbersArray.floatArrayFromStrings // [1.5, 2.3, 3.7, 4.5]
let total = doublesArray.reduce(0, +) // 12
let average = total / Double(doublesArray.count) // 3

Swift 5.1
extension Collection where Iterator.Element == String {
var convertToDouble: [Double] {
return compactMap{ Double($0) }
}
var convertToFloat: [Float] {
return compactMap{ Float($0) }
}
}
Example How to Use
let String_Array = ["1.5","2.3","3.7","4.5"] // ["1.5", "2.3", "3.7", "4.5"]
let Double_Array = String_Array.convertToDouble // [1.5, 2.3, 3.7, 4.5]
let Float_Array = String_Array.convertToFloat. // [1.5, 2.3, 3.7, 4.5]
OR You can do this
let numArray = ["1.0","2.0","3.0"]
let stringFromArray = numberArray[0]
let floatFromString = Float(stringFromArray)
let doubleFromString = Double(stringFromArray)

if you are sure that all of your array is string, you can directly cast your string into float or double.
let numberArray:Array = ["1.0","2.0","3.0"]
let stringFromArray = numberArray[0]
let floatFromString = Float(stringFromArray)
let doubleFromString = Double(stringFromArray)

Related

How to convert data into little endian format?

var val = 1240;
convert into little endian formate swift 3
Ex: 1500 (0x5DC) to 0xDC050000
let value = UInt16(bigEndian: 1500)
print(String(format:"%04X", value.bigEndian)) //05DC
print(String(format:"%04X", value.littleEndian)) //DC05
Make sure you are actually using the bigEndian initializer.
With 32-bit integers:
let value = UInt32(bigEndian: 1500)
print(String(format:"%08X", value.bigEndian)) //000005DC
print(String(format:"%08X", value.littleEndian)) //DC050000
If you want 1500 as an array of bytes in little-endian order:
var value = UInt32(littleEndian: 1500)
let array = withUnsafeBytes(of: &value) { Array($0) }
If you want that as a Data:
let data = Data(array)
Or, if you really wanted that as a hex string:
let string = array.map { String(format: "%02x", $0) }.joined()
let timeDevide = self.setmiliSecond/100
var newTime = UInt32(littleEndian: timeDevide)
let arrayTime = withUnsafeBytes(of: &newTime)
{Array($0)}
let timeDelayValue = [0x0B] + arrayTime
You can do something like
//: Playground - noun: a place where people can play
import UIKit
extension String {
func hexadecimal() -> Data? {
var data = Data(capacity: count / 2)
let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
regex.enumerateMatches(in: self, range: NSRange(location: 0, length: utf16.count)) { match, _, _ in
let byteString = (self as NSString).substring(with: match!.range)
var num = UInt8(byteString, radix: 16)!
data.append(&num, count: 1)
}
guard !data.isEmpty else { return nil }
return data
}
}
func convertInputValue<T: FixedWidthInteger>(_ inputValue: Data) -> T where T: CVarArg {
let stride = MemoryLayout<T>.stride
assert(inputValue.count % (stride / 2) == 0, "invalid pack size")
let fwInt = T.init(littleEndian: inputValue.withUnsafeBytes { $0.pointee })
let valuefwInt = String(format: "%0\(stride)x", fwInt).capitalized
print(valuefwInt)
return fwInt
}
var inputString = "479F"
var inputValue: Data! = inputString.hexadecimal()
let val: UInt16 = convertInputValue(inputValue) //9F47
inputString = "479F8253"
inputValue = inputString.hexadecimal()
let val2: UInt32 = convertInputValue(inputValue) //53829F47

Write array of Float to binary file and read it in swift

How can I write array of Floatto binary file and then read it?
var array: [Float]: [0.1, 0.2, 0.3]
func writeArrayToBinary(array: [Float]) {
//...
}
func readArrayFromBinary() -> [Float] {
//...
}
As you stated in a comment, speed is priority. Then, I suggest you write your array to a binary file (as originally requested), using the Data class, provided with Cocoa.
let url = URL(fileURLWithPath: "myTestFile.myBinExt")
// Writing
var wArray: [Float] = [1.1, 3.7, 2.5, 6.4, 7.8]
let wData = Data(bytes: &wArray, count: wArray.count * MemoryLayout<Float>.stride)
try! wData.write(to: url)
// Reading file
let rData = try! Data(contentsOf: url)
// Converting data, version 1
var rArray: [Float]?
rData.withUnsafeBytes { (bytes: UnsafePointer<Float>) in
rArray = Array(UnsafeBufferPointer(start: bytes, count: rData.count / MemoryLayout<Float>.size))
}
print(rArray!)
// Converting data, version 2
let tPointer = UnsafeMutablePointer<UInt8>.allocate(capacity: rData.count)
rData.copyBytes(to: tPointer, count: rData.count)
defer {
tPointer.deinitialize(count: rData.count)
tPointer.deallocate(capacity: rData.count)
}
var pointer = UnsafeRawPointer(tPointer) // Performs no allocation or copying; no deallocation shall be done.
// MemoryLayout<Float>.size = 4
print(pointer.load(fromByteOffset: 00, as: Float.self))
print(pointer.load(fromByteOffset: 04, as: Float.self))
print(pointer.load(fromByteOffset: 08, as: Float.self))
print(pointer.load(fromByteOffset: 12, as: Float.self))
print(pointer.load(fromByteOffset: 16, as: Float.self))
Output:
[1.10000002, 3.70000005, 2.5, 6.4000001, 7.80000019]
1.1
3.7
2.5
6.4
7.8
Please try this...
var array: [Float] = [0.1, 0.2, 0.3]
func writeArrayToPlist(array: [Float]) {
if let arrayPath: String = createArrayPath() {
(array as NSArray).writeToFile(arrayPath, atomically: false)
}
}
func readArrayFromPlist() -> [Float]? {
if let arrayPath: String = createArrayPath() {
if let arrayFromFile: [Float] = NSArray(contentsOfFile: arrayPath) as? [Float] {
return arrayFromFile
}
}
return nil
}
func createArrayPath () -> String? {
if let docsPath: String = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last {
return ((docsPath as NSString).stringByAppendingPathComponent("myArrayFileName") as NSString).stringByAppendingPathExtension("plist")
}
return nil
}

Splitting a string in swift using multiple delimiters

I am trying to split (or explode) a string in Swift (1.2) using multiple delimiters, or seperators as Apple calls them.
My string looks like this:
KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value
I have formatted it for easy reading:
KEY1=subKey1=value&subkey2=value
KEY2=subkey1=value&subkey2=value
KEY3=subKey1=value&subkey3=value
The uppercase "KEY" are predefined names.
I was trying to do this using:
var splittedString = string.componentsSeparatedByString("KEY1")
But as you can see, I can only do this with one KEY as the separator, so I am looking for something like this:
var splittedString = string.componentsSeperatedByStrings(["KEY1", "KEY2", "KEY3"])
So the result would be:
[
"KEY1" => "subKey1=value&subkey2=value",
"KEY2" => "subkey1=value&subkey2=value",
"KEY3" => "subkey1=value&subkey2=value"
]
Is there anything built into Swift 1.2 that I can use?
Or is there some kind of extension/library that can do this easily?
Thanks for your time, and have a great day!
One can also use the following approach to split a string with multiple delimiters in case keys are single characters:
//swift 4+
let stringData = "K01L02M03"
let res = stringData.components(separatedBy: CharacterSet(charactersIn: "KLM"))
//older swift syntax
let res = stringData.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "KLM"));
res will contain ["01", "02", "03"]
If anyone knows any kind of special syntax to extend the approach to multiple characters per key you are welcome to suggest and to improve this answer
Swift 4.2 update to #vir us's answer:
let string = "dots.and-hyphens"
let array = string.components(separatedBy: CharacterSet(charactersIn: ".-"))
This isn't very efficient, but it should do the job:
import Foundation
extension String {
func componentsSeperatedByStrings(ss: [String]) -> [String] {
let inds = ss.flatMap { s in
self.rangeOfString(s).map { r in [r.startIndex, r.endIndex] } ?? []
}
let ended = [startIndex] + inds + [endIndex]
let chunks = stride(from: 0, to: ended.count, by: 2)
let bounds = map(chunks) { i in (ended[i], ended[i+1]) }
return bounds
.map { (s, e) in self[s..<e] }
.filter { sl in !sl.isEmpty }
}
}
"KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value".componentsSeperatedByStrings(["KEY1", "KEY2", "KEY3"])
// ["=subKey1=value&subkey2=value", "=subkey1=value&subkey2=value", "=subKey1=value&subkey3=value"]
Or, if you wanted it in dictionary form:
import Foundation
extension String {
func componentsSeperatedByStrings(ss: [String]) -> [String:String] {
let maybeRanges = ss.map { s in self.rangeOfString(s) }
let inds = maybeRanges.flatMap { $0.map { r in [r.startIndex, r.endIndex] } ?? [] }
let ended = [startIndex] + inds + [endIndex]
let chunks = stride(from: 0, to: ended.count, by: 2)
let bounds = map(chunks) { i in (ended[i], ended[i+1]) }
let values = bounds
.map { (s, e) in self[s..<e] }
.filter { sl in !sl.isEmpty }
let keys = filter(zip(maybeRanges, ss)) { (r, _) in r != nil }
var result: [String:String] = [:]
for ((_, k), v) in zip(keys, values) { result[k] = v }
return result
}
}
"KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value".componentsSeperatedByStrings(["KEY1", "KEY2", "KEY3"])
// ["KEY3": "=subKey1=value&subkey3=value", "KEY2": "=subkey1=value&subkey2=value", "KEY1": "=subKey1=value&subkey2=value"]
For Swift 2:
import Foundation
extension String {
func componentsSeperatedByStrings(ss: [String]) -> [String] {
let unshifted = ss
.flatMap { s in rangeOfString(s) }
.flatMap { r in [r.startIndex, r.endIndex] }
let inds = [startIndex] + unshifted + [endIndex]
return inds.startIndex
.stride(to: inds.endIndex, by: 2)
.map { i in (inds[i], inds[i+1]) }
.flatMap { (s, e) in s == e ? nil : self[s..<e] }
}
}
Swift 5:
extension String {
func components<T>(separatedBy separators: [T]) -> [String] where T : StringProtocol {
var result = [self]
for separator in separators {
result = result
.map { $0.components(separatedBy: separator)}
.flatMap { $0 }
}
return result
}
}
It's for the sack of nice and neat code, don't use it if you need something efficiently
Swift 2 for forward compatibility
Using a regular expression:
let string = "KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value"
let nsString :NSString = string
let stringRange = NSMakeRange(0, string.utf16.count)
let pattern = "(KEY\\d)=([^=]+=[^&]+[^=]+?=[^K]+)"
var results = [String:String]()
do {
var regEx = try NSRegularExpression(pattern:pattern, options:[])
regEx.enumerateMatchesInString(string, options: [], range: stringRange) {
(result : NSTextCheckingResult?, _, _) in
if let result = result {
if result.numberOfRanges == 3 {
let key = nsString.substringWithRange(result.rangeAtIndex(1))
let value = nsString.substringWithRange(result.rangeAtIndex(2))
results[key] = value
}
}
}
}
catch {
print("Bad Pattern")
}
results: ["KEY3": "subKey1=value&subkey3=value", "KEY2": "subkey1=value&subkey2=value", "KEY1": "subKey1=value&subkey2=value"]
You could do it with regular expressions. The below snippet is a bit clumsy and not really fail-safe but it should give you an idea.
let string = "KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value"
let re = NSRegularExpression(pattern: "(KEY1|KEY2|KEY3)=", options: nil, error: nil)!
let matches = re.matchesInString(string, options: nil,
range: NSMakeRange(0, count(string)))
var dict = [String: String]()
for (index, match) in enumerate(matches) {
let key = (string as NSString).substringWithRange(
NSMakeRange(match.range.location, match.range.length - 1))
let valueStart = match.range.location + match.range.length
let valueEnd = index < matches.count - 1 ? matches[index + 1].range.location
: count(string)
let value = (string as NSString).substringWithRange(
NSMakeRange(valueStart, valueEnd - valueStart))
dict[key] = value
}
The final value of dict is
[KEY3: subKey1=value&subkey3=value,
KEY2: subkey1=value&subkey2=value,
KEY1: subKey1=value&subkey2=value]

Swift - How to remove a decimal from a float if the decimal is equal to 0?

I'm displaying a distance with one decimal, and I would like to remove this decimal in case it is equal to 0 (ex: 1200.0Km), how could I do that in swift?
I'm displaying this number like this:
let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: "%.1f", distanceFloat) + "Km"
Swift 3/4:
var distanceFloat1: Float = 5.0
var distanceFloat2: Float = 5.540
var distanceFloat3: Float = 5.03
extension Float {
var clean: String {
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
}
}
print("Value \(distanceFloat1.clean)") // 5
print("Value \(distanceFloat2.clean)") // 5.54
print("Value \(distanceFloat3.clean)") // 5.03
Swift 2 (Original answer)
let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: distanceFloat == floor(distanceFloat) ? “%.0f" : "%.1f", distanceFloat) + "Km"
Or as an extension:
extension Float {
var clean: String {
return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
}
}
Use NSNumberFormatter:
let formatter = NumberFormatter()
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 2
// Avoid not getting a zero on numbers lower than 1
// Eg: .5, .67, etc...
formatter.numberStyle = .decimal
let nums = [3.0, 5.1, 7.21, 9.311, 600.0, 0.5677, 0.6988]
for num in nums {
print(formatter.string(from: num as NSNumber) ?? "n/a")
}
Returns:
3
5.1
7.21
9.31
600
0.57
0.7
extension is the powerful way to do it.
Extension:
Code for Swift 2 (not Swift 3 or newer):
extension Float {
var cleanValue: String {
return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
}
}
Usage:
var sampleValue: Float = 3.234
print(sampleValue.cleanValue)
3.234
sampleValue = 3.0
print(sampleValue.cleanValue)
3
sampleValue = 3
print(sampleValue.cleanValue)
3
Sample Playground file is here.
Update of accepted answer for swift 3:
extension Float {
var cleanValue: String {
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
}
}
usage would just be:
let someValue: Float = 3.0
print(someValue.cleanValue) //prints 3
To format it to String, follow this pattern
let aFloat: Float = 1.123
let aString: String = String(format: "%.0f", aFloat) // "1"
let aString: String = String(format: "%.1f", aFloat) // "1.1"
let aString: String = String(format: "%.2f", aFloat) // "1.12"
let aString: String = String(format: "%.3f", aFloat) // "1.123"
To cast it to Int, follow this pattern
let aInt: Int = Int(aFloat) // "1"
When you use String(format: initializer, Swift will automatically round the final digit as needed based on the following number.
You can use an extension as already mentioned, this solution is a little shorter though:
extension Float {
var shortValue: String {
return String(format: "%g", self)
}
}
Example usage:
var sample: Float = 3.234
print(sample.shortValue)
Swift 5
for Double it's same as #Frankie's answer for float
var dec: Double = 1.0
dec.clean // 1
for the extension
extension Double {
var clean: String {
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
}
}
Swift 5.5 makes it easy
Just use the new formatted() api with a default FloatingPointFormatStyle:
let values: [Double] = [1.0, 4.5, 100.0, 7]
for value in values {
print(value.formatted(FloatingPointFormatStyle()))
}
// prints "1, 4.5, 100, 7"
In Swift 4 try this.
extension CGFloat{
var cleanValue: String{
//return String(format: 1 == floor(self) ? "%.0f" : "%.2f", self)
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.2f", self)//
}
}
//How to use - if you enter more then two-character after (.)point, it's automatically cropping the last character and only display two characters after the point.
let strValue = "32.12"
print(\(CGFloat(strValue).cleanValue)
Formatting with maximum fraction digits, without trailing zeros
This scenario is good when a custom output precision is desired.
This solution seems roughly as fast as NumberFormatter + NSNumber solution from MirekE, but one benefit could be that we're avoiding NSObject here.
extension Double {
func string(maximumFractionDigits: Int = 2) -> String {
let s = String(format: "%.\(maximumFractionDigits)f", self)
var offset = -maximumFractionDigits - 1
for i in stride(from: 0, to: -maximumFractionDigits, by: -1) {
if s[s.index(s.endIndex, offsetBy: i - 1)] != "0" {
offset = i
break
}
}
return String(s[..<s.index(s.endIndex, offsetBy: offset)])
}
}
(works also with extension Float, but not the macOS-only type Float80)
Usage: myNumericValue.string(maximumFractionDigits: 2) or myNumericValue.string()
Output for maximumFractionDigits: 2:
1.0 → "1"
0.12 → "0.12"
0.012 → "0.01"
0.0012 → "0"
0.00012 → "0"
Simple :
Int(floor(myFloatValue))
NSNumberFormatter is your friend
let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
let numberFormatter = NSNumberFormatter()
numberFormatter.positiveFormat = "###0.##"
let distance = numberFormatter.stringFromNumber(NSNumber(float: distanceFloat))!
distanceLabel.text = distance + " Km"
Here's the full code.
let numberA: Float = 123.456
let numberB: Float = 789.000
func displayNumber(number: Float) {
if number - Float(Int(number)) == 0 {
println("\(Int(number))")
} else {
println("\(number)")
}
}
displayNumber(numberA) // console output: 123.456
displayNumber(numberB) // console output: 789
Here's the most important line in-depth.
func displayNumber(number: Float) {
Strips the float's decimal digits with Int(number).
Returns the stripped number back to float to do an operation with Float(Int(number)).
Gets the decimal-digit value with number - Float(Int(number))
Checks the decimal-digit value is empty with if number - Float(Int(number)) == 0
The contents within the if and else statements doesn't need explaining.
This might be helpful too.
extension Float {
func cleanValue() -> String {
let intValue = Int(self)
if self == 0 {return "0"}
if self / Float (intValue) == 1 { return "\(intValue)" }
return "\(self)"
}
}
Usage:
let number:Float = 45.23230000
number.cleanValue()
Maybe stringByReplacingOccurrencesOfString could help you :)
let aFloat: Float = 1.000
let aString: String = String(format: "%.1f", aFloat) // "1.0"
let wantedString: String = aString.stringByReplacingOccurrencesOfString(".0", withString: "") // "1"

FloatValue with 2 decimals from textField

In my Core Data app I save 3 Floating point numbers from 3 UITexFields. To do that I had to convert them to Strings.
Now the problem is that the values are rounded to .0.
How do I do it?
nyTankning.liter = (textFieldLiter.text as NSString).floatValue
nyTankning.kronor = (textFieldKronor.text as NSString).floatValue
nyTankning.literpris = (textFieldLiterpris.text as NSString).floatValue
Your problem there is that you are trying to use a comma "," instead of a period "."
struct Number {
static let formatter = NumberFormatter()
}
extension String {
var converted: String? {
return fractionDigits()
}
var doubleValue: Double? {
return Number.formatter.number(from: self)?.doubleValue
}
var floatValue: Float? {
return Number.formatter.number(from: self)?.floatValue
}
func fractionDigits(min: Int = 2, max: Int = 2) -> String? {
Number.formatter.decimalSeparator = "."
if let result = Number.formatter.number(from: self) {
Number.formatter.minimumFractionDigits = min
Number.formatter.maximumFractionDigits = max
return Number.formatter.string(from: result)
} else {
Number.formatter.decimalSeparator = ","
if let result = Number.formatter.number(from: self) {
Number.formatter.minimumFractionDigits = min
Number.formatter.maximumFractionDigits = max
return Number.formatter.string(from: result)
}
}
return nil
}
}
"1,1222".converted // "1.12"
"2".converted // "2.00"
"1,1222".converted?.doubleValue // 1.12
"2".converted?.doubleValue // 2.0
"1,1222".converted?.floatValue // 1.12000000476837
"2".converted?.floatValue // 2.0
"1.1222".converted // "1.12"
"1.1222".converted?.doubleValue // 1.12
"1.254".converted?.floatValue // 1.25
"1.254".fractionDigits(min: 1, max: 2) // "1.25"
"1.2".fractionDigits(min: 1, max: 2) // "1.2"
You can use the NSString(format: "%.02f", nyTanking.liter)

Resources