Reputation: 315
I just want to convert an array into a tuple in Swift; something like the following:
>>> myArray = [1,2,3,4,5]
>>> mytuple = tuple(myArray)
>>> mytuple
(1, 2, 3, 4, 5)
What's the easiest way of doing that?
(I only started learning Swift today, so I am very, very new).
Upvotes: 28
Views: 16172
Reputation: 179
This my universal solution for copy array data to tuple. The only problem that I could not solve is to check the type of the element in the tuple and the element from the array.
/// Unsafe copy array to tuple
func unsafeCopyToTuple<ElementType, Tuple>(array: inout Array<ElementType>, to tuple: inout Tuple) {
withUnsafeMutablePointer(to: &tuple) { pointer in
let bound = pointer.withMemoryRebound(to: ElementType.self, capacity: array.count) { $0 }
array.enumerated().forEach { (bound + $0.offset).pointee = $0.element }
}
}
Upvotes: 2
Reputation: 1042
if what you want to do is extract multiple value from array at the same time, maybe the following code could help you
extension Array {
func splat() -> (Element,Element) {
return (self[0],self[1])
}
func splat() -> (Element,Element,Element) {
return (self[0],self[1],self[2])
}
func splat() -> (Element,Element,Element,Element) {
return (self[0],self[1],self[2],self[3])
}
func splat() -> (Element,Element,Element,Element,Element) {
return (self[0],self[1],self[2],self[3],self[4])
}
}
then you can use it like this
let (first,_,third) = ( 0..<20 ).map { $0 }.splat()
you can even write a codegen to generate the extension code
Upvotes: 4
Reputation: 1292
Scared of unsafe pointers? Or need support for tuples with different types inside?
It can also be done like this:
public extension Array {
public var tuple: Any? {
switch count {
case 0:
return ()
case 1:
return (self[0])
case 2:
return (self[0], self[1])
case 3:
return (self[0], self[1], self[2])
case 4:
return (self[0], self[1], self[2], self[3])
case 5:
return (self[0], self[1], self[2], self[3], self[4])
default:
return nil
}
}
Because typing this out can be a little error prone, it's a good idea to write tests for this that make sure the right tuple is returned.
I've used this approach in ArrayPlusTuple.
So instead of writing this functionality yourself you could just add pod 'ArrayPlusTuple'
to your pod file and get this tested functionality for free.
Upvotes: 2
Reputation: 22559
It's actually quite possible, if you are willing to do some low level magic. I don't think it works if the tuple has a collection type, though. This is mainly for interacting with C libraries.
typealias TupleType = (UInt8, UInt8, UInt8)
var array = [2, 3, 4] as [UInt8]
var tuple = UnsafeMutablePointer<StepsType>(malloc(UInt(sizeof(TupleType))))
memcpy(tuple, array, UInt(array.count))
More of this stuff can be found here: https://codereview.stackexchange.com/questions/84476/array-to-tuple-in-swift/84528#84528
Because 70% of us are highly visual beings:
Upvotes: 26
Reputation: 118671
You can't do this because the size of a tuple is part of its type, and this isn't true for an array. If you know the array's length, you can just do let myTuple = (myArray[0], myArray[1], ...)
. Or you can build your architecture around tuples from the beginning. What are you trying to do?
This is a common problem which occurs in lots of other languages. See How do I convert a list to a tuple in Haskell?
Upvotes: 16