How can I create a 3D Mutable Array of Int?
I want to be able to insert an element by saying arr[4][3][5] = 4, and not have to determine the size of the array beforehand.
Discussion (see below for final code)
Here is a way to do it: First we extend _ArrayType with a subscript that automatically extends the array when accessing an index out of bounds. We will the array with a given fallback value:
extension _ArrayType {
subscript (extending pos: Int, fallback fallback: Generator.Element) -> Generator.Element {
mutating get {
while count <= pos { append(fallback) }
return self[pos]
}
mutating set {
while count <= pos { append(fallback) }
self[pos] = newValue
}
}
}
This is useable like this:
var a : [Int] = []
a[extending: 3, fallback: 0] = 10
print(a) // [0, 0, 0, 10]
Now we can extend the 3-dimensional arrays to have a convenient subscript that auto-extends like this:
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType {
typealias T = Generator.Element.Generator.Element.Generator.Element
subscript (x: Int, y: Int, z: Int, `default`: T) -> T {
mutating get {
return self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: `default`]
}
mutating set {
self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: `default`] = newValue
}
}
}
Usage:
var array : [[[Int?]]] = []
array[1, 1, 0, nil] = 10
array[2, 0, 1, nil] = 4
print(array) // [[], [[], [Optional(10)]], [[nil, Optional(4)]]]
Now if you want it even more convenient by telling beforehand what the default value should be for a certain type you can create a HasDefault protocol:
protocol HasDefault {
static var `default` : Self { get }
}
And extend your types with it:
extension Int : HasDefault {
static var `default` = 0
}
extension Bool : HasDefault {
static var `default` = false
}
Also make a subscript that doesn't take the last argument:
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType,
Generator.Element.Generator.Element.Generator.Element : HasDefault {
typealias E = Generator.Element.Generator.Element.Generator.Element
subscript (x: Int, y: Int, z: Int) -> E {
mutating get {
return self[x, y, z, E.`default`]
}
mutating set {
self[x, y, z, E.`default`] = newValue
}
}
}
Now this is useable the way you want it:
var array : [[[Int]]] = []
array[0, 1, 0] = 3
array[1, 2, 3] = 10
print(array[2, 0, 1]) // 0
print(array) // [[[], [3]], [[], [], [0, 0, 0, 10]], [[0, 0]]]
Unfortunately it's not (yet) possible to extend Optional with HasDefault (which would be nil), but you can make a custom subscript for NilLiteralConvertibles which Optional conforms to:
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType,
Generator.Element.Generator.Element.Generator.Element : NilLiteralConvertible {
subscript (x: Int, y: Int, z: Int) -> Generator.Element.Generator.Element.Generator.Element {
mutating get {
return self[x, y, z, nil]
}
mutating set {
self[x, y, z, nil] = newValue
}
}
}
Use like this:
var array : [[[Int?]]] = []
array[0, 1, 0] = 3
array[1, 2, 3] = 10
print(array[2, 0, 1]) // nil
print(array) // [[[], [3]], [[], [], [nil, nil, nil, 10]], [[nil, nil]]]
I heavily recommend this approach, since the whole purpose of Optionals is to represent no value.
TL;DR / The final code
extension _ArrayType {
subscript (extending pos: Int, fallback fallback: Generator.Element) -> Generator.Element {
mutating get {
while count <= pos { append(fallback) }
return self[pos]
}
mutating set {
while count <= pos { append(fallback) }
self[pos] = newValue
}
}
}
extension _ArrayType where
Generator.Element : _ArrayType,
Generator.Element.Generator.Element : _ArrayType,
Generator.Element.Generator.Element.Generator.Element : NilLiteralConvertible {
subscript (x: Int, y: Int, z: Int) -> Generator.Element.Generator.Element.Generator.Element {
mutating get {
return self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: nil]
}
mutating set {
self[extending: x, fallback: []][extending: y, fallback: []][extending: z, fallback: nil] = newValue
}
}
}
var array : [[[Int?]]] = []
array[0, 1, 0] = 3
array[1, 2, 3] = 10
print(array[2, 0, 1]) // nil
print(array) // [[[], [3]], [[], [], [nil, nil, nil, 10]], [[nil, nil]]]
var z = [Int](count:10, repeatedValue: 0)
var y = [[Int]](count:10, repeatedValue: z)
var x = [[[Int]]](count:10, repeatedValue: y)
x[A][B][C] = 4
var val = x[2][1][1]
Swift 3 in Xcode 8 beta 2 playground
var z = [Int](repeatElement(0, count: 10))
var y = [[Int]](repeatElement(z, count: 10))
var x = [[[Int]]](repeatElement(y, count: 10))
Possible answer
var z = [0]
var y = [z]
var x = [y]
x[0][0].append(2)
x[0].append([1])
x.append([[3,5],[0]])
print(x)
x[0][0][0] = 2
print(x)
//Output
[[[0, 2], [1]], [[3, 5], [0]]]
[[[2, 2], [1]], [[3, 5], [0]]]
Related
I am trying call the defined struct so I am able to change its value when a button is pressed. I am having trouble with calling SIMD3 inside a struct. Currently I have,
struct CaptureData {
var vertices: [SIMD3<Float>]
var mode: Mode = .one
mutating func nextCase() {
mode = mode.next()
}
var verticesFormatted : String {
let v = "<" + vertices.map{ "\($0.x):\($0.y):\($0.z)" }.joined(separator: "~") + "method: \(mode.next().rawValue)"
return "\(v)"
}
}
And the extension that I got helped earlier from #Joshua
enum Mode: String, CaseIterable {
case one, two, three
}
extension CaseIterable where Self: Equatable {
var allCases: AllCases { Self.allCases }
var nextCase: Self {
let index = allCases.index(after: allCases.firstIndex(of: self)!)
guard index != allCases.endIndex else { return allCases.first! }
return allCases[index]
}
#discardableResult
func next() -> Self {
return self.nextCase
}
}
I am trying to initialize var instance = CaptureData(vertices: [SIMD3<Float>]), but the error comes: Cannot convert value of type '[SIMD3<Float>].Type' to expected argument type '[SIMD3<Float>]'
#Jousha also suggested me to use the following:
typealias XYZVar = (x: Float, y: Float, z: Float)
struct CaptureData {
var vertices:[XYZVar]
.... other variables
}
However, I also tried that with var instance = CaptureData(vertices: [XYZVar]) and it also not working: Cannot convert value of type '[XYZVar].Type' (aka 'Array<(x: Float, y: Float, z: Float)>.Type') to expected argument type '[XYZVar]' (aka 'Array<(x: Float, y: Float, z: Float)>')
My question is, how to I call SIMD3 properly and fix the above error from var instance = CaptureData(vertices: [SIMD3<Float>])?
Thanks so much in advance.
Hmm, where do I start here?
You are passing [SIMD3<Float>] and [XYZVar] which are types, to a function/initializer that expects a value as a parameter. That's why the compiler is complaining.
Let me explain.
In swift when you write var vertices: [SIMD3<Float>] you are saying: "vertices" is an array of SIMD3<Float>. Now, if you want to assign a value to "vertices" you can do so by writing vertices = [] or vertices = [SIMD3<Float>]() they are equivalent.
I did some changes to your code. Take a look:
import simd
enum Mode: String, CaseIterable {
case one, two, three
}
extension CaseIterable where Self: Equatable {
var allCases: AllCases { Self.allCases }
var nextCase: Self {
let index = allCases.index(after: allCases.firstIndex(of: self)!)
guard index != allCases.endIndex else { return allCases.first! }
return allCases[index]
}
#discardableResult
func next() -> Self {
return self.nextCase
}
}
struct CaptureData {
var vertices: [SIMD3<Float>]
var mode: Mode = .one
mutating func nextCase() {
mode = mode.next()
}
var verticesFormatted : String {
let verticesDescribed = vertices
.map({ "\($0.x):\($0.y):\($0.z)" })
.joined(separator: "~")
let v = "< \(verticesDescribed) method: \(mode.next().rawValue)"
return v
}
}
let data = CaptureData(vertices: [
SIMD3<Float>(x: 0, y: 0, z: 0),
SIMD3<Float>(x: 0.5, y: 1, z: 0),
SIMD3<Float>(x: 1, y: 0, z: 0)
])
print(data.verticesFormatted)
// prints: < 0.0:0.0:0.0~0.5:1.0:0.0~1.0:0.0:0.0 method: two
I am having trouble with a design of a Vertex struct. I want to be able to create "Array" or "Set" so my "Vertex" doesnt all have to be the same type. Both situations are giving different errors. Check code below.
Thank you in advance
import Foundation
public struct Vertex<T: Equatable> where T: Equatable, T: Hashable {
public var data: T
public let index: Int?
init(data: T , index: Int ) {
self.data = data
self.index = index
}
}
extension Vertex: CustomStringConvertible {
public var description: String {
return "\(index): \(data)"
}
}
struct Coordinate {
var x : Int
var y : Int
init(x : Int, y: Int) {
self.x = x
self.y = y
}
}
extension Coordinate: Equatable {}
func ==(lhs: Coordinate, rhs: Coordinate) -> Bool {
guard lhs.x == rhs.x else {
return false
}
guard lhs.y == rhs.y else {
return false
}
return true
}
extension Coordinate: Hashable {
var hashValue: Int {
return "\(x)\(y)".hashValue
}
}
let coord1 = Coordinate(x : 5, y: 5)
let stringVertex1 = Vertex(data: "Hello World", index: 3)
let stringVertex2 = Vertex(data: "Foo ", index: 3)
let intVertex1 = Vertex(data: 2, index: 1)
let coordVertex1 = Vertex(data: coord1, index: 1)
//Error: Cannot convert value of type 'Vertex<String>' to expected element type 'Vertex'.
//Even if I make myArr1 equal to [stringVertex1, stringVertex1], I still get the same error.
let myArr1 : Array<Vertex> = [stringVertex1, intVertex1]
//This works since the data inside "Vertex" is the same type.
let myArr2 : Array<Vertex<String>> = [stringVertex1, stringVertex2]
//Error: Type "Vertex" does not conform to protocol "Hashable".
let mySet1 : Set<Vertex> = [stringVertex1, stringVertex2]
I got my answer. This is the final vertex code. THE POWER OF POP!
public enum TypeOfVertex : String {
case Int = "Mirror for Int"
case Float = "Mirror for Float"
case Double = "Mirror for Double"
case Coordinates = "Mirror for Coordinate"
case String = "Mirror for String"
}
protocol AnyVertexable {
var type: TypeOfVertex { get set }
var index: Int { get set }
}
struct Vertex<Element : Hashable> : AnyVertexable where Element: Equatable & Hashable {
var type : TypeOfVertex
var index: Int
var data : Element?
init(index: Int, data: Element) {
self.data = data
self.index = index
if let type = TypeOfVertex(rawValue: data.hashValue.customMirror.description) {
self.type = type
} else {
fatalError()
}
}
}
let sample1 = Vertex(index: 0, data: 1.0)
let sample2 = Vertex(index: 2, data: 1)
let sample3 = Vertex(index: 3, data: Coordinate(x: 5, y: 5))
let myArr : [AnyVertexable] = [sample1, sample2, sample3]
I have a class A:
class A {
var identifier: String?
var quantity: Int = 0
}
Two arrays of A instances:
var array1: [A] = [a1, a2, a3, a4]
var array2: [A] = [a5, a6, a7, a8]
I don't know which is the best way to check:
array1==array2 if a1.identifier == a5.identifier, a2.identifier == a6.identifier, a3.identifier==a7.identifier, a4.identifier==a8.identifier in Swift.
Please help me...
You can try like this:
let result = zip(array1, array2).enumerated().filter() {
$1.0 == $1.1
}.map{$0.0}
Swift 4
The following method makes it much more easy.
Method 1 - Using Equatable Protocol
Step1 - Make your class 'A' equatable as follows
extension A: Equatable {
static func ==(lhs: A, rhs: A) -> Bool {
// Using "identifier" property for comparison
return lhs.identifier == rhs.identifier
}
}
Step2 - Sort your arrays in ascending or descending order
let lhsArray = array1.sorted(by: { $0.identifier < $1.identifier })
let rhsArray = array2.sorted(by: { $0.identifier < $1.identifier })
Step3 - Use == or elementsEqual comparison
let isEqual = lhsArray == rhsArray
OR
let isEqual = lhsArray.elementsEqual(rhsArray, by: { $0 == $1} )
Method 2 (Without Equatable Protocol)
Step 1 - Sort Array as described in Method1, step 2
Step 2 - Use elementsEqual
lhsArray.elementsEqual(rhsArray, by: { $0.identifier == $1.identifier })
Read more about Array Comparison here
Assume your data like that:
struct Person
{
let name: String
let id: Int
}
var people1 = [
Person(name: "Quang Hà", id: 42),
Person(name: "Lý Hải", id: 23),
Person(name: "Maria", id: 99)
]
var people2 = [
Person(name: "Maria yyy", id: 99),
Person(name: "Billy", id: 42),
Person(name: "David", id: 23)
]
This is the method to compare two arrays of people with id:
func areArrayPeopleEqual(people1:[Person], people2: [Person]) -> Bool {
var array1 = people1
var array2 = people2
// Don't equal size => false
if array1.count != array2.count {
return false
}
// sort two arrays
array1.sortInPlace() { $0.id > $1.id }
array2.sortInPlace() {$0.id > $1.id }
// get count of the matched items
let result = zip(array1, array2).enumerate().filter() {
$1.0.id == $1.1.id
}.count
if result == array1.count {
return true
}
return false
}
This method could be used if you have some parameter to compare:
let difference = currentObjects
.filter({ currentObject in
!(newObjects
.contains(where: { $0.identifier == currentObject.identifier }))
})
I found this really easy solution at https://www.hackingwithswift.com/example-code/language/how-to-find-the-difference-between-two-arrays
extension Array where Element: Hashable {
func difference(from other: [Element]) -> [Element] {
let thisSet = Set(self)
let otherSet = Set(other)
return Array(thisSet.symmetricDifference(otherSet))
}
}
let names1 = ["a1", "A4", "a3", "a4"]//["John", "Paul", "Ringo"]
let names2 = ["a1", "a5", "a4","a1.1"]//["Ringo", "George"]
let difference = names1.difference(from: names2)
First we extend Equatable class, to have a DRY code, than if the 2 arrays are always of the same size, or if at least the first one is <= than the second you can go with this solution.
Pay attention that you are working with optionals, you may have to unwrap them before.
class A {
var identifier: String?
var quantity: Int = 0
init(identifier: String, quantity: Int) {
self.identifier = identifier
self.quantity = quantity
}
}
let a1: A = A(identifier: "1", quantity: 1)
let a2: A = A(identifier: "2", quantity: 2)
let a3: A = A(identifier: "3", quantity: 3)
let a4: A = A(identifier: "4", quantity: 4)
let a5: A = A(identifier: "1", quantity: 1)
let a6: A = A(identifier: "2", quantity: 2)
let a7: A = A(identifier: "3", quantity: 3)
let a8: A = A(identifier: "4", quantity: 4)
var array1: [A] = [a1, a2, a3, a4]
var array2: [A] = [a5, a6, a7, a8]
func areEquals(array1: [A], array2: [A]) -> Bool {
if array1.count < array2.count {
return false
}
for i in 0...array2.count - 1 {
if array1[i] != array2[i] {
return false
}
}
return true
}
extension A: Equatable {
static func ==(lhs: A, rhs: A) -> Bool {
//you can choose how and when they should be equals
return lhs.identifier == rhs.identifier
}
}
try this code, let me know if it works
func toDictionary<E, K, V>(
array: [E],
transformer: (element: E) -> (key: K, value: V)?)
-> Dictionary<K, V>
{
return array.reduce([:]) {
(var dict, e) in
if let (key, value) = transformer(element: e)
{
dict[key] = value
}
return dict
}
}
then you can execute a check like below
let areEqual = array1.count == array2.count;
if areEqual {
let dict1 = toDictionary(array1) { ($0.identifier, $0.quantity) }
let dict2 = toDictionary(array2) { ($0.identifier, $0.quantity) }
areEqual = NSDictionary(dictionary: dict1).isEqualToDictionary(dict2)
}
print(areEqual)
disclaimer: function toDictionary has been took form here
Wondering if there is a clean way of doing this in Swift. Maybe using one or a couple of the global functions, ie Map / Reduce etc
The array contains unique custom objects of n quantity.
For example, with 3 items. But could have more or less. [1,2,3]
Would return an Array of Arrays
[
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
]
Here is a way in Java to complete the task. Just need to get into Swift form.
https://gist.github.com/JadenGeller/5d49e46d4084fc493e72
He created structs to handle permutations:
var greetingPermutations = PermutationSequenceGenerator(elements: ["hi", "hey", "hello"])
while let greetingSequence = greetingPermutations.next(){
for greeting in greetingSequence {
print("\(greeting) ")
}
println()
}
or:
var numberSpace = PermutationSpaceGenerator(objects: Array(1...4))
while let numberArray = numberSpace.next() {
println(numberArray)
}
EDIT:
Here is a simpler way found on objc.io
Add Extension
extension Array {
var decompose : (head: T, tail: [T])? {
return (count > 0) ? (self[0], Array(self[1..<count])) : nil
}
}
Add outside your extension / and class
infix operator >>= {}
func >>=<A, B>(xs: [A], f: A -> [B]) -> [B] {
return xs.map(f).reduce([], combine: +)
}
Normal Class Functions
func between<T>(x: T, ys: [T]) -> [[T]] {
if let (head, tail) = ys.decompose {
return [[x] + ys] + between(x, ys: tail).map { [head] + $0 }
} else {
return [[x]]
}
}
func permutations<T>(xs: [T]) -> [[T]] {
if let (head, tail) = xs.decompose {
return permutations(tail) >>= { permTail in
self.between(head, ys: permTail)
}
} else {
return [[]]
}
}
Testing
let example = permutations([1,2,3,5,6,7,8])
println(example)
This code extends Array with decompose function and also adds >>== operator (flattening) More about flattening: http://www.objc.io/snippets/4.html
Probably too c-ish, but here is an alternative to the already posted examples.
var a = [1, 2, 3, 4, 5]
var b = [[Int]]()
func perms<T>(n: Int, inout a: [T], inout b: [[T]]) {
if n == 0 {
b.append(a)
} else {
for i in 0..<n {
perms(n - 1, &a, &b)
var j = 0
if n % 2 == 0 {
j = i
}
swap(&a[j], &a[n - 1])
}
}
}
perms(a.count, &a, &b)
println(b)
Swift 5
Updated version of #DogCoffee for swift 5.x, all within an array extension :
extension Array {
private var decompose : (head: Element, tail: [Element])? {
return (count > 0) ? (self[0], Array(self[1..<count])) : nil
}
private func between<T>(x: T, ys: [T]) -> [[T]] {
if let (head, tail) = ys.decompose {
return [[x] + ys] + between(x: x, ys: tail).map { [head] + $0 }
} else {
return [[x]]
}
}
private func permutations<T>(xs: [T]) -> [[T]] {
if let (head, tail) = xs.decompose {
return permutations(xs: tail) >>= { permTail in
self.between(x: head, ys: permTail)
}
} else {
return [[]]
}
}
func allPermutations() -> [[Element]] {
return permutations(xs: self)
}
}
infix operator >>=
func >>=<A, B>(xs: [A], f: (A) -> [B]) -> [B] {
return xs.map(f).reduce([], +)
}
I know how to do it in java (see here), but I couldn't find a swift equivalent for java's ByteBuffer, and consequently its .putDouble(double value) method.
Basically, I'm looking for a function like this:
func doubleToByteArray(value: Double) -> [UInt8]? {
. . .
}
doubleToByteArray(1729.1729) // should return [64, 155, 4, 177, 12, 178, 149, 234]
typealias Byte = UInt8
func toByteArray<T>(var value: T) -> [Byte] {
return withUnsafePointer(&value) {
Array(UnsafeBufferPointer(start: UnsafePointer<Byte>($0), count: sizeof(T)))
}
}
toByteArray(1729.1729)
toByteArray(1729.1729 as Float)
toByteArray(1729)
toByteArray(-1729)
But the results are reversed from your expectations (because of endianness):
[234, 149, 178, 12, 177, 4, 155, 64]
[136, 37, 216, 68]
[193, 6, 0, 0, 0, 0, 0, 0]
[63, 249, 255, 255, 255, 255, 255, 255]
Added:
func fromByteArray<T>(value: [Byte], _: T.Type) -> T {
return value.withUnsafeBufferPointer {
return UnsafePointer<T>($0.baseAddress).memory
}
}
let a: Double = 1729.1729
let b = toByteArray(a) // -> [234, 149, 178, 12, 177, 4, 155, 64]
let c = fromByteArray(b, Double.self) // -> 1729.1729
For Xcode8/Swift3.0:
func toByteArray<T>(_ value: T) -> [UInt8] {
var value = value
return withUnsafePointer(to: &value) {
$0.withMemoryRebound(to: UInt8.self, capacity: MemoryLayout<T>.size) {
Array(UnsafeBufferPointer(start: $0, count: MemoryLayout<T>.size))
}
}
}
func fromByteArray<T>(_ value: [UInt8], _: T.Type) -> T {
return value.withUnsafeBufferPointer {
$0.baseAddress!.withMemoryRebound(to: T.self, capacity: 1) {
$0.pointee
}
}
}
For Xcode8.1/Swift3.0.1
func toByteArray<T>(_ value: T) -> [UInt8] {
var value = value
return withUnsafeBytes(of: &value) { Array($0) }
}
func fromByteArray<T>(_ value: [UInt8], _: T.Type) -> T {
return value.withUnsafeBytes {
$0.baseAddress!.load(as: T.self)
}
}
Well, it wasn't easy, but here it is:
func doubleToByteArray(value: Double) -> [UInt8] {
let count = sizeof(Double)
var doubles: [Double] = [value]
let data = NSData(bytes: doubles, length: count)
var result = [UInt8](count: count, repeatedValue: 0)
data.getBytes(&result, length: count)
return result
}
Use with caution.
Here's my updated version to the original solution.
/// input: array of bytes
/// -> get pointer to byte array (UnsafeBufferPointer<[Byte]>)
/// -> access its base address
/// -> rebind memory to target type T (UnsafeMutablePointer<T>)
/// -> extract and return the value of target type
func binarytotype <T> (_ value: [Byte], _: T.Type) -> T
{
return value.withUnsafeBufferPointer {
$0.baseAddress!
.withMemoryRebound(to: T.self, capacity: 1) {
$0.pointee
}
}
}
/// input type: value of type T
/// -> get pointer to value of T
/// -> rebind memory to the target type, which is a byte array
/// -> create array with a buffer pointer initialized with the source pointer
/// -> return the resulted array
func typetobinary <T> (_ value: T) -> [Byte]
{
var mv : T = value
let s : Int = MemoryLayout<T>.size
return withUnsafePointer(to: &mv) {
$0.withMemoryRebound(to: Byte.self, capacity: s) {
Array(UnsafeBufferPointer(start: $0, count: s))
}
}
}
PS: Don't forget to replace Byte with UInt8.
Solution in swift 3:
public func toByteArray<T>(_ value: T) -> [Byte] {
let totalBytes = MemoryLayout<T>.size
var value = value
return withUnsafePointer(to: &value) { valuePtr in
return valuePtr.withMemoryRebound(to: Byte.self, capacity: totalBytes) { reboundPtr in
return Array(UnsafeBufferPointer(start: reboundPtr, count: totalBytes))
}
}
}
The accepted answers are dangerous because of the fact that the MemoryLayout provides you the size of the static type T!
To workaround the problem you should create a custom protocol and ask for Self in it:
protocol ByteConvertible {}
extension ByteConvertible {
func toBytes() -> [UInt8] {
let capacity = MemoryLayout<Self>.size
var mutableValue = self
return withUnsafePointer(to: &mutableValue) {
return $0.withMemoryRebound(to: UInt8.self, capacity: capacity) {
return Array(UnsafeBufferPointer(start: $0, count: capacity))
}
}
}
}
I mentioned before that the accepted answers are dangerous and here is an example why:
let num = UInt8(42)
MemoryLayout.size(ofValue: num) //=> 1 byte as expected
let any: Any = num
MemoryLayout.size(ofValue: any) //=> 32 bytes which is what will happen in the generic functions from the all the answers
Swift 3.0
The method above works, using Swift 2 but, I discovered a much more simpler and faster method to do this conversion and vice versa:
func binarytotype <T> (value: [UInt8], _: T.Type) -> T
{
return value.withUnsafeBufferPointer
{
return UnsafePointer<T>($0.baseAddress).memory
}
}
func typetobinary <T> (var value: T) -> [UInt8]
{
return withUnsafePointer(&value)
{
Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>($0), count: sizeof(T)))
}
}
let a: Double = 0.25
let b: [UInt8] = typetobinary(a) // -> [0, 0, 0, 0, 0, 0, 208, 63]
let c = binarytotype(b, Double.self) // -> 0.25
I have tested it with Xcode 7.2 in the playground.
func byteArray<T>(_ value: T) -> [UInt8] {
var value = value
var initialArray = withUnsafeBytes(of: &value) { Array($0) }
initialArray.reverse()
var count = initialArray.count
while initialArray.first == 0 && count > 1 {
initialArray[0...count - 2] = initialArray[1...count - 1]
count -= 1
}
if initialArray[0] >= 128 {
var newArray = [UInt8](repeating: 0, count: count + 1)
newArray[0] = UInt8(0)
newArray[1...count] = initialArray[0...count - 1]
return newArray
} else {
return Array(initialArray[0...count - 1])
}
}