4
\$\begingroup\$

I have a situation where I needed to convert NSNumber 2D array to Float 2D array, so I did it like this:

var numArr:[[NSNumber]]()
//fill values
let floatArr = numArr.map { $0.map { $0.floatValue} }

It's working fine, no issues!

But I wondering if there's any better way to handle this?

\$\endgroup\$
5
\$\begingroup\$

Your code is fine, an equivalent method in Swift 3 would be

let floatArr = numArr.map { $0.map { Float($0) } }

You get the same result with less code by using the bridging cast from NSNumber to Float, which works for (nested) arrays as well:

if let floatArr = numArr as [[Float]] { ... }

Actually I don't know of any case (in Swift 3) where this cast can fail.

Things change a bit in Swift 4, as a consequence of SE 0170 - NSNumber bridging and Numeric types. Your code still works fine, and is equivalent to

let floatArr = numArr.map { $0.map { Float(truncating: $0) } }

The truncating initializers where introduced because not every Number can be converted to a scalar value without loosing information, there are also failable init?(exactly:) initializers.

Now the bridged cast can fail

  • for numbers which are not exactly representable as a Float, such as Double(1.1),
  • for numbers which exceed the range of Float.

(The first case is currently discussed at https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170612/037499.html and may change in the future.)

Example:

let numArr = [
    [ NSNumber(value: 1.1), NSNumber(value: 2.0) ],
    [ NSNumber(value: Double.greatestFiniteMagnitude) ],
]

if let floatArr = numArr as? [[Float]] {
    print(floatArr)
} else {
    print("failed")
}

This produces [[1.10000002, 2.0], [inf]] in Swift 3, but fails in Swift 4.

To summarize: Your code is fine.

  • If you don't care about "loosing precision" or overflows then there is no need to change anything. In Swift 4 you can write it as Float(truncating: $0) to emphasize that the result might not be exactly identical to the given numbers.
  • If you care then you can use the new "exactly" initializers, or the bridged cast as? [[Float]] in Swift 4.
\$\endgroup\$

This site is temporarily in read only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .