i am trying to convert a Int16 into [UInt8] like that:
var track:Int16 = 4
let trackData = Data(bytes: &track, count: 2)
but the result is
[4, 0]
I was wondering if there is a way to get
[0, 4]
So when I do :
let value = Int16(bigEndian: trackData.withUnsafeBytes { $0.pointee })
I would get 4 instead of 1024
it is not much a rocket-science but byteSwapped may do the job for you, like:
let value = Int16(bigEndian: trackData.withUnsafeBytes { $0.pointee }).byteSwapped
that would make the value 4 in your case.
NOTE: even Apple Docs does not say too much about this property (kinda self explanatory, to be honest), so just for the sake of completion, here comes the reference of byteSwapped.
Related
How does subscripting a lazy filter work?
let ary = [0,1,2,3]
let empty = ary.lazy.filter { $0 > 4 }.map { $0 + 1 }
print(Array(empty)) // []
print(empty[2]) // 3
It looks like it just ignores the filter and does the map anyway. Is this documented somewhere? What other lazy collections have exceptional behavior like this?
It comes down to subscripting a LazyFilterCollection with an integer which in this case ignores the predicate and forwards the subscript operation to the base.
For example, if we're looking for the strictly positive integers in an array :
let array = [-10, 10, 20, 30]
let lazyFilter = array.lazy.filter { $0 > 0 }
print(lazyFilter[3]) // 30
Or, if we're looking for the lowercase characters in a string :
let str = "Hello"
let lazyFilter = str.lazy.filter { $0 > "Z" }
print(lazyFilter[str.startIndex]) //H
In both cases, the subscript is forwarded to the base collection.
The proper way of subscripting a LazyFilterCollection is using a LazyFilterCollection<Base>.Index as described in the documentation :
let start = lazyFilter.startIndex
let index = lazyFilter.index(start, offsetBy: 1)
print(lazyFilter[index])
Which yields 20 for the array example, or l for the string example.
In your case, trying to access the index 3:
let start = empty.startIndex
let index = empty.index(start, offsetBy: 3)
print(empty)
would raise the expected runtime error :
Fatal error: Index out of range
To add to Carpsen90's answer, you run into one of Collection's particularities: it's not recommended, nor safe to access collections by an absolute index, even if the type system allows this. Because the collection you receive might be a subset of another one.
Let's take a simpler example, array slicing:
let array = [0, 1, 2, 3, 4]
let slice = array[2..<3]
print(slice) // [2]
print(slice.first) // Optional(2)
print(slice[0]) // crashes with array index out of bounds
Even if slice is a collection indexable by an integer, it's still unsafe to use absolute integers to access elements of that collection, as the collection might have a different set of indices.
So, currently I have this dictionary:
var data : [Int:Float] = [0:0,1:1,2:1.414,3:2.732,4:2,5:5.236,6:3.469,7:2.693,8:5.828,9:3.201]
I want to create a new dictionary, say "newData." I want "newData" to have the same keys as "data," but I want to multiply every value in "data" by some constant (say "multiple") to get the values in "newData." How can I do this?
Thanks!
var newData = data
for (key, value) in newData
{
newData[key] = value * multiple
}
Given
let data : [Int:Float] = [0:0,1:1,2:1.414,3:2.732,4:2,5:5.236,6:3.469,7:2.693,8:5.828,9:3.201]
let factor: Float = 2
You can use the reduce method
let multiplied = data.reduce([Int:Float]()) { (var result, elm) -> [Int:Float] in
result[elm.0] = elm.1 * factor
return result
}
The result.
[3: 5.464, 2: 2.828, 4: 4.0, 9: 6.402, 5: 10.472, 6: 6.938, 7: 5.386, 0: 0.0, 8: 11.656, 1: 2.0]
Please ignore the order since Dictionaries do not have one.
Why this solution is better then a for loop?
The code I am suggesting here does follow the Functional Programming paradigm. There are several advantages over the classic for loop:
It's thread safe: since only immutable values are used, you don't have to worry about other threads that could change these values while you are using them.
It's faster: under the hood the elements of the results are processed in parallel
It's less error prone because it's more declarative: we are describing how the result should be, not how to build it.
Another solution based on map
let dict1 = ["a":1, "b":2, "c":3]
// Make a copy since we don't want to modify the original
var dict2 = dict1
let multiple = 5
dict2.map { (k,v) in dict2[k] = v*multiple }
I did some simple performance testing with a 10000 and 100000 element array the various solutions proposed perform like this
For Loop: 10000 elements 1.28 ms, 100000 elements 12.28 ms
Map(): 10000 elements 1.24 ms, 100000 elements 12.23 ms
Reduce(): 10000 elements 2.36 ms, 100000 elements 17.18 ms
But you don't have a 10000+ element array. It's just worth noting the difference.
Since Swift 4, Dictionary has a property called mapValues(_:). mapValues(_:) has the following declaration:
Returns a new dictionary containing the keys of this dictionary with the values transformed by the given closure.
func mapValues<T>(_ transform: (Value) throws -> T) rethrows -> Dictionary<Key, T>
The Swift 5 Playground sample code below shows how to use mapValues(_:) in order to create a new dictionary by multiplying every value of an existing dictionary:
let multiple: Float = 2
let data: [Int : Float] = [0 : 0, 1 : 1, 2 : 1.4, 3 : 2.7, 4 : 2, 5 : 5.2]
let newData = data.mapValues { (value: Float) -> Float in
return value * multiple
}
//let newData = data.mapValues { $0 * multiple } // also works
print(newData) // [3: 5.4, 4: 4.0, 2: 2.8, 0: 0.0, 1: 2.0, 5: 10.4]
I read "The swift programming language" and the subscript make me confused, there's a example below with subscript, but I could also implement it with a function, so what the subscript exactly mean compared with function?
There were same output "6 times 3 is 18" with below example.
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimesTable(multiplier: 3)
println("6 times 3 is \(threeTimesTable[6])")
struct TimesTable2 {
let multiplier: Int
func times (index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable2 = TimesTable2(multiplier: 3)
println("6 times 3 is \(threeTimesTable2.times(6))")
Subscripts are a subset of functions. They can't quite do all the things a function can do (they can't take inout parameters, for instance), but they do other things very well, with a very convenient syntax (the square brackets [ ]).
They are most often used to retrieve an item from a collection by its index. So instead of having to write,
let array = [7, 3, 6, 8]
let x = array.itemAtIndex(0) // x == 7
we can just write,
let x = array[0]
Or instead of,
let dictionary = ["one": 1, "two": 2]
let x = dictionary.objectForKey("one") // x == Optional(1)
we can just write,
let x = dictionary["one"] // x == Optional(1)
The syntax is short and intuitive. And as Okapi said, they can act as getters and as setters for variable properties, just like a computed property.
The example in the documentation is a somewhat non-traditional use of subscripts. I think it is supposed to illustrate the very point that you are making - subscripts can be used in place of a function or a computed property just about anywhere that you think the [bracket] syntax would be convenient and useful. Their use is not limited to accessing items in a collection.
You get to refine your own syntactic sugar.
I want to convert a positive number into the respective list of digits -- the digits should be Ints as well.
When converting, say 1024, it should return [1,0,2,4]
in Swift 4.1 or above
let number = 1024
let digits = String(number).compactMap { Int(String($0)) }
print(digits) // [1, 0, 2, 4]
in Swift4
let number = 1024
let digits = String(number).flatMap { Int(String($0)) }
print(digits) // [1, 0, 2, 4]
in Swift2 and also Swift3
let number = 1024
let digits = String(number).characters.flatMap { Int(String($0)) }
print(digits) // [1, 0, 2, 4]
You don’t need to convert it to an array first. Since strings are collections, you can use the free (non-member) version of map:
map(number) { String($0).toInt() }
But beware your !. If number ever contains a non-numeric digit, your code will crash at runtime. And if the number is negative, it'll start with a "-".
How you want to handle this depends on what you want to do with negative numbers (maybe you want all the digits to be negative). But if you just wanted to ditch the leading "-" you could do something like:
let strNum = number >= 0 ? String(number) : dropFirst(String(number))
let digits = map(strNum) { String($0).toInt()! }
But just in case there's another possible non-numeric character for string representations of integer, you might find it better to do:
let digits = map(String(number)) { String($0).toInt() }.filter { $0 != nil }.map { $0! }
After some searching and some trial and error approach using the Swift REPL, I came up with this
var digits:[Int] = Array(String(number)).map { String($0).toInt()! }
Note that the !is critical
Can we change any pair value in let type Dictionary in Swift Langauage.
like :
let arr2 : AnyObject[] = [1, "23", "hello"]
arr2[1] = 23
arr2 // output: [1,23,"hello"]
let arr1 :Dictionary<Int,AnyObject> = [1: "One" , 2 : 2]
arr1[2] = 4 // not posible error
arr1
In Case of Immutable Array we can change its value like above but not in case of Immutable
Dictionary. Why?
This is taken from The Swift Programming Language book:
For dictionaries, immutability also means that you cannot replace the
value for an existing key in the dictionary. An immutable dictionary’s
contents cannot be changed once they are set.
Immutability has a slightly different meaning for arrays, however. You
are still not allowed to perform any action that has the potential to
change the size of an immutable array, but you are allowed to set a
new value for an existing index in the array.
Array declared with let has only immutable length. Contents can still be changed.
Dictionary declared with let is completely immutable, you can't change contents of it. If you want, you must use var instead of let.
Swift has changed a lot since then.
Array and Dictionary are value types. When declared with let, they cannot change any more. Especially, one cannot re-assign them, or the elements in them.
But if the type of the elements is reference type, you can change the properties of the elements in Array or Dictionary.
Here is a sample.(run in Xcode6 beta-6)
class Point {
var x = 0
var y = 0
}
let valueArr: [Int] = [1, 2, 3, 4]
let refArr: [Point] = [Point(), Point()]
valueArr[0] = -1 // error
refArr[0] = Point() // error
refArr[0].x = 1
let valueDict: [Int : Int] = [1: 1, 2: 2]
let refDict: [Int: Point] = [1: Point(), 2: Point()]
valueDict[1] = -1 //error
refDict[1] = Point() //error
refDict[1]!.x = -1