Related
How do I convert a UInt32 value to 4 bytes in swift?
I have a value of (3) when I get;
IPP_ORIENTATION.PORTRAIT.rawValue
Now, I need to convert that value into 4 bytes.
Thanks.
let value: UInt32 = 1
var u32LE = value.littleEndian // or simply value
let dataLE = Data(bytes: &u32LE, count: 4)
let bytesLE = Array(dataLE) // [1, 0, 0, 0]
var u32BE = value.bigEndian
let dataBE = Data(bytes: &u32BE, count: 4)
let bytesBE = Array(dataBE) // [0, 0, 0, 1]
I have a string with the following format:
var cadenaCoordenadas = """
1,1
1,3
4,1
5,1
1,5
1,6
2,5
0,0
"""
What I want is that each line is in the following format (in an array) to manipulate it (with Int data types as I will do operations with the new string):
[1,1]
I have the following code:
var arregloEntradas = cadenaCoordenadas.split(separator: "\n")
print("primer Arreglo: ", arregloEntradas)
for i in stride(from: 0, through:arregloEntradas.count - 1, by: 1){
let arregloEntradasFinal = arregloEntradas[i].split(separator: ",")
print(arregloEntradasFinal)
}
and I get the result of this:
this is the result
as you can see, the array elements are of string type, however I require them to be of Int type:
[1,1]
[1,3]
[4,1]
...
I hope you can help me, thank you in advance.
Here's one approach using some splitting and mapping:
var cadenaCoordenadas = """
1,1
1,3
4,1
5,1
1,5
1,6
2,5
0,0
"""
let arregloEntradasFinal = cadenaCoordenadas.split(separator: "\n")
.map { $0.split(separator: ",").compactMap { Int($0) } }
print(arregloEntradasFinal)
Output:
[[1, 1], [1, 3], [4, 1], [5, 1], [1, 5], [1, 6], [2, 5], [0, 0]]
var arregloEntradas = cadenaCoordenadas.split(separator: "\n")
print("primer Arreglo: ", arregloEntradas)
for i in stride(from: 0, through:arregloEntradas.count - 1, by: 1){
let arregloEntradasFinal = arregloEntradas[i].split(separator: ",").map { Int(String($0)) }
print(arregloEntradasFinal)
}
What you're getting in arregloEntradasFinal is correct since you're processing the string array. Later, when you want to use arregloEntradasFinal again, you should again split a string by a comma separator from arregloEntradasFinal and use the individual Int value. For example:
let index = 0 // You can also loop through the array
let values = arregloEntradasFinal[index].split(separator: ",")
let num1 = Int(values.first ?? 0) // If no value then returns 0
let num2 = Int(values.last ?? 0) // If no value then returns 0
Note - this is one of the way without using the map function.
I have an array with integers [1, 2, 3, 7, 13, 11, 4] and an integer value 12. I need to return an array of a closest combination of sum of the integer values in the new array.
For example: [1, 2, 3, 7, 13, 11, 4] with value 12. The array that need to returned is [1, 2, 3, 4] because the sum of elements 1 + 2 + 3 + 4 <= 12. This is the longest array and prefered over [1, 7, 4] 1 + 7 + 4 = 12.
this solution works if you dont have repeated numbers in array.
var array = [1, 2, 3, 7, 13, 11, 4, -12, 22, 100]
print(array.sorted())
let value = 19
func close(array: [Int], value: Int) -> (Int , Int) {
let sortedArray = array.sorted()
var lastNumberBeforValue = sortedArray.first!
for (index,number) in sortedArray.enumerated() {
let sub = value - number
if sub > 0 {
lastNumberBeforValue = number
}
if sortedArray.contains(sub) && sub != number {
return (sub, number)
} else if index == sortedArray.count - 1 {
if sub < 0 {
let near = close(array: array, value: value - lastNumberBeforValue)
return (near.0, lastNumberBeforValue)
}
let near = close(array: array, value: sub)
return (near.0, number)
}
}
return (-1,-1)
}
let numbers = close(array: array, value: value)
print(numbers) //prints (4, 13)
This solution also finds the two Integers in an array which sum is closest to a given value:
let array = [1, 2, 3, 7, 13, 11, 4]
let value = 5
var difference = Int.max
var result = [Int(), Int()]
for firstInt in array {
for secondInt in array {
let tempDifference = abs((firstInt + secondInt) - value)
if tempDifference < difference {
difference = tempDifference
result[0] = firstInt
result[1] = secondInt
}
}
}
Or a solution that doesn't allow multiple use of the same value:
for (firstIndex, firstInt) in array.enumerated() {
for (secondIndex, secondInt) in array.enumerated() {
guard firstInt != secondInt else { break }
let tempDifference = abs((firstInt + secondInt) - value)
if tempDifference < difference {
difference = tempDifference
result[0] = firstInt
result[1] = secondInt
}
}
}
You can keep on nesting for-loops and guarding for multiple use of same index, if you want longer result arrays. Finally you can take the valid array with the largest result.count. This is not a vary nice solution though, since it computationally heavy, and requires the array to have a static length.
I'm not necessary good with algorithms but I would do it like that :
Since your rule is <= 5 you can sort your array : [1, 2, 3, 7, 13, 11, 4] => [1, 2, 3, 4, 7, 11, 13]
Then, as you don't need integer > 5 you can split your array in 2 parts and take only the first one : [1, 2, 3, 4]
From there you have to add 4 + 3 and match with your value. If it doesn't work do 4 + 2, then 4 + 1. If it's still > 5, loop with 3,2 ; 3,1 ; etc. I did something like this in a Swift way :
// Init
let array = [1, 2, 3, 7, 13, 11, 4]
let value = 5
let sortedArray = array.sorted()
let usefulArray = sortedArray.filter() {$0 < value}
var hasCombination = false
var currentIndex = usefulArray.count - 1
var indexForSum = currentIndex - 1
// Process
if currentIndex > 0 {
hasCombination = true
while usefulArray[currentIndex] + usefulArray[indexForSum] > value {
indexForSum -= 1
if indexForSum < 0 {
currentIndex -= 1
indexForSum = currentIndex - 1
}
if currentIndex == 0 {
hasCombination = false
break
}
}
}
// Result
if hasCombination {
let combination = [usefulArray[indexForSum], usefulArray[currentIndex]]
} else {
print("No combination")
}
I guess it works, tell me if it doesn't !
There must be some really elegant way of copying end of the Array using Swift starting from some index, but I just could not find it, so I ended with this:
func getEndOfArray<T>( arr : [T], fromIndex : Int? = 0) -> [T] {
var i=0;
var newArray : [T] = [T]()
for item in arr {
if i >= fromIndex {
newArray.append(item)
}
i = i + 1;
}
return newArray // returns copy of the array starting from index fromIndex
}
Is there a better way of doing this without extra function?
And another one ...
let array = [1, 2, 3, 4, 5]
let fromIndex = 2
let endOfArray = array.dropFirst(fromIndex)
print(endOfArray) // [3, 4, 5]
This gives an ArraySlice which should be good enough for most
purposes. If you need a real Array, use
let endOfArray = Array(array.dropFirst(fromIndex))
An empty array/slice is created if the start index is larger than (or equal to) the element count.
You can use suffix:
let array = [1,2,3,4,5,6]
let lastTwo = array.suffix(2) // [5, 6]
As mentioned in the comment: This gives you an ArraySlice object which is sufficient for most cases. If you really need an Array object you have to cast it:
let lastTwoArray = Array(lastTwo)
You can subscript an open ended range now. This will include elements starting at index 5.
Swift 4.2
array[5...]
This is one possible solution, there are probably a few more
let array = [1, 2, 3, 4, 5]
let endOfArray = Array(array[2..<array.endIndex]) // [3, 4, 5]
Or with dynamic index and range check
let array = [1, 2, 3, 4, 5]
let index = 2
let endOfArray : [Int]
if index < array.count {
endOfArray = Array(array[index..<array.endIndex]) // [3, 4, 5]
} else {
endOfArray = array
}
The re-initializition of the array is needed since the range subscription of Array returns ArraySlice<Element>
You could use the new method removeFirst(_:) in Swift 4
var array = [1, 2, 3, 4, 5]
array.removeFirst(2)
print(array) // [3, 4, 5]
You could use filter
func getEndOfArray( arr : [Int], fromIndex : Int? = 0) -> [Int] {
let filteredArray = arr.filter({$0 <= fromIndex})
return filteredArray
}
took the liberty of changing to [Int] for the sake of this example.
In my app, I have 2 arrays which are in use a lot, an array that stores score values as an Integer, and another array that stores dates in the format "mm/dd/yy". These arrays are continuously being appended, and the indexes of these arrays correspond to each other, for example, index 0 of dates array corresponds to index 0 of score array. I want these arrays to be turned into a dictionary upon when a second screen loads(these are global variables). For example, these are the type of values in each array.
score == [1,2,3,4,5,6,7,8,9]
dates == ["7/12/15","7/12/15","7/12/15","7/12/15","7/13/15","7/13/15","7/13/15","7/13/15"," 7/14/15"]
What I want to happen, is that upon viewDidLoad(), this gets created.
var scoreDatesDictionary = [
"7/12/15": [1,2,3,4]
"7/13/15": [5,6,7,8]
"7/14/15": [9]
]
In its essence, the two arrays have corresponding values, (firstArray[0]) corresponds to (secondArray[0]). I am trying to make it that in the secondArray(dates), identical strings get matched up in a dictionary with their corresponding index values. I may not make much sense, but the sample code I provided should work. I spent a lot of time working with this, and I can't find a solution.
let score = [1,2,3,4,5,6,7,8,9,]
let dates = ["7/12/15","7/12/15","7/12/15","7/12/15","7/13/15","7/13/15","7/13/15","7/13/15"," 7/14/15"]
var dic = [String:[Int]]()
for var index=0;index < dates.count; index++ {
let key = dates[index];
var value = dic[key]
if value == nil{
dic[key] = [score[index]]
}else{
value!.append(score[index])
dic[key] = value
}
}
println(dic)
This will log
[7/12/15: [1, 2, 3, 4], 7/14/15: [9], 7/13/15: [5, 6, 7, 8]]
func zipToDict<
S0 : SequenceType,
S1 : SequenceType where
S0.Generator.Element : Hashable
>(keys: S0, values: S1) -> [S0.Generator.Element:[S1.Generator.Element]] {
var dict: [S0.Generator.Element:[S1.Generator.Element]] = [:]
for (key, value) in zip(keys, values) {
dict[key] = (dict[key] ?? []) + [value]
}
return dict
}
let score = [1,2,3,4,5,6,7,8,9]
let dates = ["7/12/15","7/12/15","7/12/15","7/12/15","7/13/15","7/13/15","7/13/15","7/13/15"," 7/14/15"]
print(zipToDict(dates, score)) // [7/12/15: [1, 2, 3, 4], 7/14/15: [9], 7/13/15: [5, 6, 7, 8]]
Working off #Leo's correct answer, here's a version that makes use of enumerate and the nil coalescing operator ?? to do this more cleanly:
For Swift 1.2:
let score = [1,2,3,4,5,6,7,8,9]
let dates = ["7/12/15","7/12/15","7/12/15","7/12/15","7/13/15","7/13/15","7/13/15","7/13/15"," 7/14/15"]
var dic = [String:[Int]]()
for (index, date) in enumerate(dates) {
dic[date] = (dic[date] ?? []) + [score[index]]
}
print(dic) // prints "[7/12/15: [1, 2, 3, 4], 7/14/15: [9], 7/13/15: [5, 6, 7, 8]]"
For Swift 2.0, you need to use dates.enumerate() instead.