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])
}
}
Related
I have structs like
struct RGBA: Codable {
var r: UInt8
var g: UInt8
var b: UInt8
var a: UInt8
}
I want save large amount of this structs (>1_000_000)
Decode
guard let history = try? JSONDecoder().decode(HistoryRGBA.self, from: data) else { return }
Encode
guard let jsonData = try? encoder.encode(dataForSave) else { return false }
How can I improve encoding/decoding time and amount of RAM memory?
The performance of JSONEncoder/Decoder performance is...not great. ZippyJSON is a drop-in replacement that is supposedly about 4 times faster than Foundation's implmenetation, and if you're going for better performance and lower memory usage, you'll probably want to Google for some kind of streaming JSON decoder library.
However, you said in the comments that you don't need the JSON format. That's great, because we can store the data much more efficiently as just an array of raw bytes rather than a text-based format such as JSON:
extension RGBA {
static let size = 4 // the size of a (packed) RGBA structure
}
// encoding
var data = Data(count: history.rgba.count * RGBA.size)
for i in 0..<history.rgba.count {
let rgba = history.rgba[i]
data[i*RGBA.size] = rgba.r
data[i*RGBA.size+1] = rgba.g
data[i*RGBA.size+2] = rgba.b
data[i*RGBA.size+3] = rgba.a
}
// decoding
guard data.count % RGBA.size == 0 else {
// data is incomplete, handle error
return
}
let rgbaCount = data.count / RGBA.size
var result = [RGBA]()
result.reserveCapacity(rgbaCount)
for i in 0..<rgbaCount {
result.append(RGBA(r: data[i*RGBA.size],
g: data[i*RGBA.size+1],
b: data[i*RGBA.size+2],
a: data[i*RGBA.size+3]))
}
This is already about 50 times faster than using JSONEncoder on my machine (~100ms instead of ~5 seconds).
You can get even faster by bypassing some of Swift's safety checks and memory management and dropping down to raw pointers:
// encoding
let byteCount = history.rgba.count * RGBA.size
let rawBuf = malloc(byteCount)!
let buf = rawBuf.bindMemory(to: UInt8.self, capacity: byteCount)
for i in 0..<history.rgba.count {
let rgba = history.rgba[i]
buf[i*RGBA.size] = rgba.r
buf[i*RGBA.size+1] = rgba.g
buf[i*RGBA.size+2] = rgba.b
buf[i*RGBA.size+3] = rgba.a
}
let data = Data(bytesNoCopy: rawBuf, count: byteCount, deallocator: .free)
// decoding
guard data.count % RGBA.size == 0 else {
// data is incomplete, handle error
return
}
let result: [RGBA] = data.withUnsafeBytes { rawBuf in
let buf = rawBuf.bindMemory(to: UInt8.self)
let rgbaCount = buf.count / RGBA.size
return [RGBA](unsafeUninitializedCapacity: rgbaCount) { resultBuf, initializedCount in
for i in 0..<rgbaCount {
resultBuf[i] = RGBA(r: data[i*RGBA.size],
g: data[i*RGBA.size+1],
b: data[i*RGBA.size+2],
a: data[i*RGBA.size+3])
}
}
}
Benchmark results on my machine (I did not test ZippyJSON):
JSON:
Encode: 4967.0ms; 32280478 bytes
Decode: 5673.0ms
Data:
Encode: 96.0ms; 4000000 bytes
Decode: 19.0ms
Pointers:
Encode: 1.0ms; 4000000 bytes
Decode: 18.0ms
You could probably get even faster by just writing your array directly from memory to disk without serializing it at all, although I haven't tested that either. And of course, when you're testing performance, be sure you're testing in Release mode.
Considering that all your properties are UInt8 (bytes) you can make your struct conform to ContiguousBytes and save its raw bytes:
struct RGBA {
let r, g, b, a: UInt8
}
extension RGBA: ContiguousBytes {
func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
try Swift.withUnsafeBytes(of: self) { try body($0) }
}
}
extension ContiguousBytes {
init<T: ContiguousBytes>(_ bytes: T) {
self = bytes.withUnsafeBytes { $0.load(as: Self.self) }
}
}
extension RGBA: ExpressibleByArrayLiteral {
typealias ArrayLiteralElement = UInt8
init(arrayLiteral elements: UInt8...) {
self.init(elements)
}
}
extension Array {
var bytes: [UInt8] { withUnsafeBytes { .init($0) } }
var data: Data { withUnsafeBytes { .init($0) } }
}
extension ContiguousBytes {
var bytes: [UInt8] { withUnsafeBytes { .init($0) } }
var data: Data { withUnsafeBytes { .init($0) } }
}
extension ContiguousBytes {
func object<T>() -> T { withUnsafeBytes { $0.load(as: T.self) } }
func objects<T>() -> [T] { withUnsafeBytes { .init($0.bindMemory(to: T.self)) } }
}
extension ContiguousBytes {
var rgba: RGBA { object() }
var rgbaCollection: [RGBA] { objects() }
}
extension UIColor {
convenience init<T: Collection>(_ bytes: T) where T.Index == Int, T.Element == UInt8 {
self.init(red: CGFloat(bytes[0])/255,
green: CGFloat(bytes[1])/255,
blue: CGFloat(bytes[2])/255,
alpha: CGFloat(bytes[3])/255)
}
}
extension RGBA {
var color: UIColor { .init(bytes) }
}
let red: RGBA = [255, 0, 0, 255]
let green: RGBA = [0, 255, 0, 255]
let blue: RGBA = [0, 0, 255, 255]
let redBytes = red.bytes // [255, 0, 0, 255]
let redData = red.data // 4 bytes
let rgbaFromBytes = redBytes.rgba // RGBA
let rgbaFromData = redData.rgba // RGBA
let colorFromRGBA = red.color // r 1.0 g 0.0 b 0.0 a 1.0
let rgba: RGBA = [255,255,0,255] // RGBA yellow
let yellow = rgba.color // r 1.0 g 1.0 b 0.0 a 1.0
let colors = [red, green, blue] // [{r 255, g 0, b 0, a 255}, {r 0, g 255, b 0, a 255}, {r 0, g 0, b 255, a 255}]
let colorsData = colors.data // 12 bytes
let colorsFromData = colorsData.rgbaCollection // [{r 255, g 0, b 0, a 255}, {r 0, g 255, b 0, a 255}, {r 0, g 0, b 255, a 255}]
edit/update:
struct LayerRGBA {
var canvas: [[RGBA]]
}
extension LayerRGBA {
var data: Data { canvas.data }
init(_ data: Data) { canvas = data.objects() }
}
struct AnimationRGBA {
var layers: [LayerRGBA]
}
extension AnimationRGBA {
var data: Data { layers.data }
init(_ data: Data) {
layers = data.objects()
}
}
struct HistoryRGBA {
var layers: [LayerRGBA] = []
var animations: [AnimationRGBA] = []
}
extension HistoryRGBA {
var data: Data {
let layersData = layers.data
return layersData.count.data + layersData + animations.data
}
init(data: Data) {
let index = Int(Data(data.prefix(8))).advanced(by: 8)
self.init(layers: data.subdata(in: 8..<index).objects(),
animations: data.subdata(in: index..<data.endIndex).objects())
}
}
extension Numeric {
var data: Data {
var bytes = self
return .init(bytes: &bytes, count: MemoryLayout<Self>.size)
}
}
extension Numeric {
init<D: DataProtocol>(_ data: D) {
var value: Self = .zero
let _ = withUnsafeMutableBytes(of: &value, { data.copyBytes(to: $0)} )
self = value
}
}
Playground testing:
let layer1: LayerRGBA = .init(canvas: [colors,[red],[green, blue]])
let layer2: LayerRGBA = .init(canvas: [[red],[green, rgba]])
let loaded: LayerRGBA = .init(layer1.data)
loaded.canvas[0]
loaded.canvas[1]
loaded.canvas[2]
let animationRGBA: AnimationRGBA = .init(layers: [layer1,layer2])
let loadedAnimation: AnimationRGBA = .init(animationRGBA.data)
loadedAnimation.layers.count // 2
loadedAnimation.layers[0].canvas[0]
loadedAnimation.layers[0].canvas[1]
loadedAnimation.layers[0].canvas[2]
loadedAnimation.layers[1].canvas[0]
loadedAnimation.layers[1].canvas[1]
let hRGBA: HistoryRGBA = .init(layers: [loaded], animations: [animationRGBA])
let loadedHistory: HistoryRGBA = .init(data: hRGBA.data)
loadedHistory.layers[0].canvas[0]
loadedHistory.layers[0].canvas[1]
loadedHistory.layers[0].canvas[2]
loadedHistory.animations[0].layers[0].canvas[0]
loadedHistory.animations[0].layers[0].canvas[1]
loadedHistory.animations[0].layers[0].canvas[2]
loadedHistory.animations[0].layers[1].canvas[0]
loadedHistory.animations[0].layers[1].canvas[1]
If anyone else like me was wondering if using PropertyListEncoder/Decoder or writing custom encoding/decoding methods for Codable structs can make any difference in performance then I made some tests to check it and the answer is that they can improve it a little bit compared to standard JSONEncoder/Decoder but not much. I can't really recommended this as there are far faster ways of doing it in other answers but I think it might be useful in some cases so I'm putting the results here. Using unkeyedContainer for encoding/decoding Codable made encoding about 2x faster in my tests but it had minimal impact on decoding and using PropertyListEncoder/Decoder made only minimal difference as pasted below. Test code:
struct RGBA1: Codable {
var r: UInt8
var g: UInt8
var b: UInt8
var a: UInt8
}
struct RGBA2 {
var r: UInt8
var g: UInt8
var b: UInt8
var a: UInt8
}
extension RGBA2: Codable {
func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(r)
try container.encode(g)
try container.encode(b)
try container.encode(a)
}
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
r = try container.decode(UInt8.self)
g = try container.decode(UInt8.self)
b = try container.decode(UInt8.self)
a = try container.decode(UInt8.self)
}
}
class PerformanceTests: XCTestCase {
var rgba1: [RGBA1] = {
var rgba1: [RGBA1] = []
for i in 0..<1_000_000 {
rgba1.append(RGBA1(r: UInt8(i % 256), g: UInt8(i % 256), b: UInt8(i % 256), a: UInt8(i % 256)))
}
return rgba1
}()
var rgba2: [RGBA2] = {
var rgba2: [RGBA2] = []
for i in 0..<1_000_000 {
rgba2.append(RGBA2(r: UInt8(i % 256), g: UInt8(i % 256), b: UInt8(i % 256), a: UInt8(i % 256)))
}
return rgba2
}()
func testRgba1JsonEncoding() throws {
var result: Data?
self.measure { result = try? JSONEncoder().encode(rgba1) }
print("rgba1 json size: \(result?.count ?? 0)")
}
func testRgba1JsonDecoding() throws {
let result = try? JSONEncoder().encode(rgba1)
self.measure { _ = try? JSONDecoder().decode([RGBA1].self, from: result!) }
}
func testRgba1PlistEncoding() throws {
var result: Data?
self.measure { result = try? PropertyListEncoder().encode(rgba1) }
print("rgba1 plist size: \(result?.count ?? 0)")
}
func testRgba1PlistDecoding() throws {
let result = try? PropertyListEncoder().encode(rgba1)
self.measure { _ = try? PropertyListDecoder().decode([RGBA1].self, from: result!) }
}
func testRgba2JsonEncoding() throws {
var result: Data?
self.measure { result = try? JSONEncoder().encode(rgba2) }
print("rgba2 json size: \(result?.count ?? 0)")
}
func testRgba2JsonDecoding() throws {
let result = try? JSONEncoder().encode(rgba2)
self.measure { _ = try? JSONDecoder().decode([RGBA2].self, from: result!) }
}
func testRgba2PlistEncoding() throws {
var result: Data?
self.measure { result = try? PropertyListEncoder().encode(rgba2) }
print("rgba2 plist size: \(result?.count ?? 0)")
}
func testRgba2PlistDecoding() throws {
let result = try? PropertyListEncoder().encode(rgba2)
self.measure { _ = try? PropertyListDecoder().decode([RGBA2].self, from: result!) }
}
}
Results on my device:
testRgba1JsonEncoding average 5.251 sec 32281065 bytes
testRgba1JsonDecoding average 7.749 sec
testRgba1PlistEncoding average 4.811 sec 41001610 bytes
testRgba1PlistDecoding average 7.529 sec
testRgba2JsonEncoding average 2.546 sec 16281065 bytes
testRgba2JsonDecoding average 7.906 sec
testRgba2PlistEncoding average 2.710 sec 25001586 bytes
testRgba2PlistDecoding average 6.432 sec
I'm building an iOS app that deals with binary and decimal outputs when a user types in a binary or decimal number. I have it to where a user can calculate one value, but how can I get it to where they can calculate multiple values in the same UITextField? Like they can type in 145, 10010110, 10011101, etc. and it can return the opposite binary or decimal.
My existing code is:
class BinaryDecimal {
var bits: [Int]?
var integer: Int?
init(_ bits: [Int]) {
self.bits = bits
}
init(_ decimal: Int) {
self.integer = decimal
}
func calculateBinaryValueForInt() -> String {
var newInt = integer!
let rows = [128, 64, 32, 16, 8, 4, 2, 1]
var binaryRows: [Int] = []
for row in rows {
let binaryDigit = oneOrZero(forValue: newInt, withBitValue: row)
binaryRows.append(binaryDigit)
if binaryDigit == 1 {
newInt = newInt - row
}
}
let stringFromIntArray = binaryRows.map { String($0) }
return stringFromIntArray.joined()
}
func calculateIntValueForBinary() -> String {
var value = 0
var multiplier = 1
guard let bits = bits else { return "Error" }
for bit in bits.reversed() {
let newValue = bit * multiplier
value = value + newValue
multiplier = multiplier * 2
}
return String(value)
}
func oneOrZero(forValue value: Int, withBitValue bitvalue: Int) -> Int {
if value - bitvalue >= 0 {
return 1
} else {
return 0
}
}
}
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]]]
I have a bunch of Objects stored in an Array.
They all have the property:
distanceInSeconds: Int
I was wondering if there's a way to find the max of this property between all objects in the array using filter or another array method?
For instance:
var distances: [Distance] = []
var maxDistance = distances.filter(find max)
This would be the Swifty way (by implementing Comparable):
class Route : Comparable {
let distance: Int
init(distance: Int) {
self.distance = distance
}
}
func ==(lhs: Route, rhs: Route) -> Bool {
return lhs.distance == rhs.distance
}
func <(lhs: Route, rhs: Route) -> Bool {
return lhs.distance < rhs.distance
}
let routes = [
Route(distance: 4),
Route(distance: 8),
Route(distance: 2),
Route(distance: 7)
]
print(routes.maxElement()?.distance)
output:
"8"
This works with Swift 2. If you're using Swift 1.2, maxElement(routes) should work
In Swift 2.0 minElement and maxElement now return optionals in case of empty sequences, and also now have versions that take isOrderedBefore closures.
let maxDistance = distances.maxElement { (a, b) -> Bool in
a.distanceInSeconds < b.distanceInSeconds
}
#1. The element type inside your sequence conforms to Comparable protocol
With Swift 4, if the element type inside your sequence conforms to Comparable protocol, you will be able to use the max() method that has the following declaration:
func max() -> Self.Element?
Returns the maximum element in the sequence.
Usage:
class Distance: Comparable, CustomStringConvertible {
let distanceInSeconds: Int
var description: String { return "Distance in Int: \(distanceInSeconds)" }
init(distanceInSeconds: Int) {
self.distanceInSeconds = distanceInSeconds
}
static func ==(lhs: Distance, rhs: Distance) -> Bool {
return lhs.distanceInSeconds == rhs.distanceInSeconds
}
static func <(lhs: Distance, rhs: Distance) -> Bool {
return lhs.distanceInSeconds < rhs.distanceInSeconds
}
}
let distances = [
Distance(distanceInSeconds: 20),
Distance(distanceInSeconds: 30),
Distance(distanceInSeconds: 10)
]
let maxDistance = distances.max()
print(String(describing: maxDistance)) // prints: Optional(Distance in Int: 30)
#2. The element type inside your sequence does not conform to Comparable protocol
With Swift 4, if the element type inside your sequence does not conform to Comparable protocol, you will have to use the max(by:) method that has the following declaration:
func max(by areInIncreasingOrder: ((offset: Int, element: Base.Element), (offset: Int, element: Base.Element)) throws -> Bool) rethrows -> (offset: Int, element: Base.Element)?
Returns the maximum element in the sequence, using the given predicate as the comparison between elements.
Usage:
class Distance: CustomStringConvertible {
let distanceInSeconds: Int
var description: String { return "Distance in Int: \(distanceInSeconds)" }
init(distanceInSeconds: Int) {
self.distanceInSeconds = distanceInSeconds
}
}
let distances = [
Distance(distanceInSeconds: 20),
Distance(distanceInSeconds: 30),
Distance(distanceInSeconds: 10)
]
let maxDistance = distances.max (by: { (a, b) -> Bool in
return a.distanceInSeconds < b.distanceInSeconds
})
print(String(describing: maxDistance)) // prints: Optional(Distance in Int: 30)
I think you want reduce:
Setup:
struct Distance {
var distanceInSeconds: Int
}
var distances: [Distance] = []
for _ in 1...10 {
distances += [Distance(distanceInSeconds: Int(arc4random_uniform(100)))]
}
Implementation:
let max = distances.reduce(distances.first) {
if let left = $0 where left.distanceInSeconds > $1.distanceInSeconds {
return $0
} else {
return $1
}
}
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([], +)
}