Convert String Array into Int Array Swift 2? - arrays

[Xcode 7.1, iOS 9.1]
I have an array: var array: [String] = ["11", "43", "26", "11", "45", "40"]
I want to convert that (each index) into an Int so I can use it to countdown from a timer, respective of the index.
How can I convert a String array into an Int Array in Swift 2?
I've tried several links, none have worked and all of them have given me an error. Most of the code from the links is depreciated or hasn't been updated to swift 2, such as the toInt() method.

Use the map function
let array = ["11", "43", "26", "11", "45", "40"]
let intArray = array.map { Int($0)!} // [11, 43, 26, 11, 45, 40]
Within a class like UIViewController use
let array = ["11", "43", "26", "11", "45", "40"]
var intArray = Array<Int>!
override func viewDidLoad() {
super.viewDidLoad()
intArray = array.map { Int($0)!} // [11, 43, 26, 11, 45, 40]
}
If the array contains different types you can use flatMap (Swift 2) or compactMap (Swift 4.1+) to consider only the items which can be converted to Int
let array = ["11", "43", "26", "Foo", "11", "45", "40"]
let intArray = array.compactMap { Int($0) } // [11, 43, 26, 11, 45, 40]

Swift 4, 5:
Use compactMap with cast to Int, solution without '!'.
let array = ["1","foo","0","bar","100"]
let arrayInt = array.compactMap { Int($0) }
print(arrayInt)
// [1, 0, 100]

Swift 4, 5:
The instant way if you want to convert string numbers into arrays of type int (in a particular case i've ever experienced):
let pinString = "123456"
let pin = pinString.map { Int(String($0))! }
And for your question is:
let pinArrayString = ["1","2","3","4","5","6"]
let pinArrayInt = pinArrayString.map { Int($0)! }

i suggest a little bit different approach
let stringarr = ["1","foo","0","bar","100"]
let res = stringarr.map{ Int($0) }.enumerate().flatMap { (i,j) -> (Int,String,Int)? in
guard let value = j else {
return nil
}
return (i, stringarr[i],value)
}
// now i have an access to (index in orig [String], String, Int) without any optionals and / or default values
print(res)
// [(0, "1", 1), (2, "0", 0), (4, "100", 100)]

A slightly different example
let digitNames = [0: "Zero", 1: "One", 2:"Two", 3: "Three",
4:"Four",5:"Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine", 10:"Ten"
]
let numbers = [16,58,510]
let strings = numbers.map { (number) -> String in
var number = number
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return (output)
}
print(strings)
// strings is inferred to be of type [String]
// its value is ["OneSix", "FiveEight", "FiveOneZero"]

Related

Swift Get x number of elements from an array

I would appreciates some help from someone who knows what they are doing as opposed to me with Arrays in Swift for Xcode.
I have an array of over 40+ heart rate readinsg that I get from an Apple Watch and want to make a new array of only exactly 40 to show on a graph, but they have to be in order, I don't want them to be out of order, so I can't use random or shuffle and get the first 40 or the last 40 of the doubles.
e.g. heartratereadings = [56.0, 57.0, 58.0 ... 101.0]
var fortyReadings = ??heartratereading.somthing to get 40 values in the order they were in?
What is a way I can do that? Thanks in advance ~ Kurt
Thanks you for the solution below I was able to great a cute graph on the watch that shows heart rate readings over time by using 40 instances of a line that is 200px hight. Then I use the individual heart rate to set the heights of each of the 40 bars. Looks great, obviously nt meant for any scientific or medical purpose, just gives me a rough idea of how the heart rate changes over given time. Apples simulator only gives heart rate readings from 58-62 so I can't wait to test. Thank you!!
This is similar to what #staticVoidMan suggested. Instead of recursion, the indices of the new (smaller) array are mapped to indices of the old (larger) array via linear interpolation:
extension Array {
/// Return a smaller array by picking “evenly distributed” elements.
///
/// - Parameter length: The desired array length
/// - Returns: An array with `length` elements from `self`
func pick(length: Int) -> [Element] {
precondition(length >= 0, "length must not be negative")
if length >= count { return self }
let oldMax = Double(count - 1)
let newMax = Double(length - 1)
return (0..<length).map { self[Int((Double($0) * oldMax / newMax).rounded())] }
}
}
Examples:
let doubleArray = [56.0, 57.0, 58.0, 98.0, 101.0, 88.0, 76.0]
print(doubleArray.pick(length: 5))
// [56.0, 58.0, 98.0, 88.0, 76.0]
let intArray = Array(1...10)
print(intArray.pick(length: 8))
// [1, 2, 4, 5, 6, 7, 9, 10]
For starters, this basic extension on Array adds the functionality to return alternate elements from any type of array:
extension Array {
func evenlySpaced(length: Int) -> [Element] {
guard length < self.count else { return self }
let takeIndex = (self.count / length) - 1
let nextArray = Array(self.dropFirst(takeIndex + 1))
return [self[takeIndex]] + nextArray.evenlySpaced(length: length - 1)
}
}
Example 1:
let doubleArray = [56.0, 57.0, 58.0, 98.0, 101.0, 88.0, 76.0]
print(doubleArray.evenlySpaced(length: 5))
[56.0, 57.0, 58.0, 98.0, 101.0, 88.0, 76.0]
evenly spaced would give:
[56.0, 57.0, 58.0, 101.0, 76.0]
Example 2:
let intArray = (1...1000).map { $0 }
print(intArray.evenlySpaced(length: 40))
This shows that if you had an array of 1000 elements, the chosen interval values would be:
[25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, 375, 400, 425, 450, 475, 500, 525, 550, 575, 600, 625, 650, 675, 700, 725, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000]
It's a simple implementation and you could loosely say it's evenly spaced because it tends to favour the initial elements in data sets that are small when compared to the requested length.
Example 3:
let array = (1...10).map { $0 }
print(array.evenlySpaced(length: 8))
[1, 2, 3, 4, 5, 6, 8, 10]
You could instead implement a more balanced logic but the general idea would be the same.
Here is the simplest way to do so:
var heartRateReading = [56.0, 57.0, 58.0, 98.0, ..., 101.0]
//If you want 40 items from the 10th position
var fortySelected = heartRateReading.suffix(from: 10).suffix(40)
// If you want to iterate each second and get 40 values out of it
_ = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (_) in
let values = heartRateReading.suffix(40)
print(values)
}
To get X number of elements from Y index we can have generic function like below:
func fetchElements<T>(sourceArray: [T],
startIndex: Int,
recordCount: Int) -> [T] {
guard startIndex >= 0 && recordCount >= 0 else { return [] }
guard startIndex < sourceArray.count else { return [] }
let arrTrimmedFromStartIndex = Array(sourceArray.suffix(from: startIndex))
let arrWithRequiredCount = Array(arrTrimmedFromStartIndex.prefix(recordCount))
return arrWithRequiredCount
}
Now we can use it with any type as below:
class MyModel {
let name: String
init(name: String) {
self.name = name
}
}
Call to actual function:
let arr = (0..<10).map({ MyModel(name: "\($0)") })
let result = fetchElements(sourceArray: arr,
startIndex: 4,
recordCount: 3)
print(arr.map({$0.name}))
print(result.map({$0.name}))
Print result:
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
["4", "5", "6"]
Hope this helps!
Just use a for loop
Var forty = [double]()
For n in 1...40 {
forty.insert(heartRate[n], at: 0)
}

Swift inputing characters and strings into a dictionary

How would I go about Writing a function that takes in an array of strings and outputs a dictionary with the first character of each string as a key and the remaining as objects?
Writing this piece of code for you without seeing any trials from your side, just because you are new on StackOverflow. And I'm seeing the message from StackOverflow that "Corey Townsend is a new contributor. Be nice..."
So I'm just being nice for you as a welcome and here is your code.
let arr = ["car", "cat", "dog", "ball", "flower", "notebook", "fire"]
func createDictionaryFromArrayAsCoreyWants(arr:[String]) -> [String:String] {
var dict:[String:String] = [:]
arr.forEach({ (word:String) in
let strKey = String(word.prefix(1))
let startIndex: String.Index = word.index(word.startIndex, offsetBy: 1)
let strValue = String(word[startIndex..<word.endIndex])
dict[strKey] = strValue
print(strKey + " : " + strValue)
})
return dict
}
let d = createDictionaryFromArrayAsCoreyWants(arr: arr)
print(d)
Addition
Just saw a comment on another answer by 'Alex Bailer' so adding one more function for you. Enjoy...
func createDictionaryFromArrayAsCoreyWants(arr:[String]) -> [String:[String]] {
var dict:[String:[String]] = [:]
arr.forEach({ (word:String) in
let strKey = String(word.prefix(1))
let startIndex: String.Index = word.index(word.startIndex, offsetBy: 1)
let strValue = String(word[startIndex..<word.endIndex])
if let a = dict[strKey] {
dict[strKey] = a + [strValue]
} else {
dict[strKey] = [strValue]
}
print(strKey + " : " + strValue)
})
return dict
}
let d = createDictionaryFromArrayAsCoreyWants(arr: arr)
print(d)
Output:
["d": ["og"], "n": ["otebook"], "b": ["all"], "c": ["ar", "at"], "f": ["lower", "ire"]]
Is this what are you looking for?
let d = Dictionary(grouping: array, by: {$0.prefix(1)})
with array:
let array = ["car", "cat", "dog", "ball", "flower", "notebok", "fire"]
It prints:
["b": ["ball"], "f": ["flower", "fire"], "d": ["dog"], "c": ["car", "cat"], "n": ["notebok"]]
And then, remove the first letter from values:
for key in d.keys {
let values = d[key]
let start = String.Index(encodedOffset: 1)
d[key] = values?.compactMap({ String($0[start...]) })
}
Output:
["f": ["lower", "ire"], "d": ["og"], "b": ["all"], "c": ["ar", "at"], "n": ["otebok"]]

Reverse array by group size

I was trying to solve this challenge: reverse an array of elements by groups given a group size.
Given Array: [1, 2, 3, 4, 5, 6]
Desired Result (group size of 3): [4, 5, 6, 1, 2, 3]
If last group has less elements than the group size, then just add them and finish, as follows:
Given Array: [1, 2, 3, 4, 5, 6, 7]
Desired Result: [5, 6, 7, 2, 3, 4, 1]
I tried this and it is working, but it looks kinda weird for me. Can anyone help me find a cleaner or much more intuitive solution?
extension Array {
func reverse(groupSize: Int) -> [Element] {
var reversed = [Element]()
let groups = count / groupSize
for group in 0...groups {
let lowerBound = count - group * groupSize - groupSize
let upperBound = count - 1 - group * groupSize
if lowerBound >= 0 {
reversed += Array(self[lowerBound...upperBound])
} else {
reversed += Array(self[0...upperBound])
}
}
return reversed
}
}
The following solution is based on a combo of stride+map:
let groupSize = 3
let array = [1, 2, 3, 4, 5, 6]
let reversedArray = Array(array.reversed())
let result = stride(from: 0, to: reversedArray.count, by: groupSize).map {
reversedArray[$0 ..< min($0 + groupSize, reversedArray.count)].reversed()
}.reduce([Int](), +)
print(result) // [4, 5, 6, 1, 2, 3]
You could say:
extension Array {
func groupedReversing(stride: Int) -> [Element] {
precondition(stride > 0, "stride must be > 0")
return Swift.stride(from: count, to: 0, by: -stride)
.flatMap { self[Swift.max(0, $0 - stride) ..< $0] }
}
}
let result = Array(1 ... 7).groupedReversing(stride: 3)
print(result) // [5, 6, 7, 2, 3, 4, 1]
We're using stride(from:through:by:) to iterate from array.count (inclusive) to 0 (exclusive) in increments of (minus) the stride. The Swift. prefix is in order to disambiguate it from the obsoleted Swift 2 stride method (which will be gone in Swift 4.1).
Then, we're flat-mapping the index to a slice of the input array that's up to stride elements long (truncating at the beginning of the array as we clamp the lower index to 0). And because this is flatMap, the resulting slices are concatenated into a single resulting array.
You could also implement a fully generic version across Sequence by first providing an implementation on BidirectionalCollection, advancing indices backwards and appending slices into a resulting array:
extension BidirectionalCollection {
func groupedReversing(stride: Int) -> [Element] {
precondition(stride > 0, "stride must be > 0")
var result: [Element] = []
result.reserveCapacity(numericCast(count))
var upper = endIndex
while upper != startIndex {
// get the next lower bound for the slice, stopping at the start index.
let lower = index(upper, offsetBy: -numericCast(stride),
limitedBy: startIndex) ?? startIndex
result += self[lower ..< upper]
upper = lower
}
return result
}
}
and then implement an overload on Sequence that first converts to an array, and then forwards onto the above implementation:
extension Sequence {
func groupedReversing(stride: Int) -> [Element] {
return Array(self).groupedReversing(stride: stride)
}
}
Now you can call it on, for example, a CountableClosedRange without first having to convert it to an array:
let result = (1 ... 7).groupedReversing(stride: 3)
print(result) // [5, 6, 7, 2, 3, 4, 1]
I think your function is okay, not sure what you meant by weird tbh, can separate to chunk or add each elements in reversed way ,but logic is same anyway, just need to mind the performance/complexity of each ways:
let a = [1,2,3,4,5,6,7,8,9,10,11]
extension Array {
func reverse(group: Int) -> [Element] {
guard group > 1 else { return self.reversed() }
var new = [Element]()
for i in stride(from: self.count-1, through: 0, by: -group) {
let k = i-group+1 < 0 ? 0 : i-group+1
for j in k...i {
new.append(self[j])
}
}
return new
}
}
a.reverse(group: 4) //[8, 9, 10, 11, 4, 5, 6, 7, 1, 2, 3]
The two following Swift 5 code snippets show how to implement a Collection or Array extension method in order to chunked it, reverse it then flatten it into a new array.
#1. Using AnyIterator and Sequence joined()
extension Collection {
func reverseFlattenChunked(by distance: Int) -> [Element] {
precondition(distance > 0, "distance must be greater than 0")
var index = endIndex
let iterator = AnyIterator({ () -> SubSequence? in
let newIndex = self.index(index, offsetBy: -distance, limitedBy: self.startIndex) ?? self.startIndex
defer { index = newIndex }
return index != self.startIndex ? self[newIndex ..< index] : nil
})
return Array(iterator.joined())
}
}
Usage:
let array = ["1", "2", "3", "4", "5", "6", "7"]
let newArray = array.reverseFlattenChunked(by: 3)
print(newArray) // prints: ["5", "6", "7", "2", "3", "4", "1"]
let array: [String] = ["1", "2", "3", "4", "5", "6"]
let newArray = array.reverseFlattenChunked(by: 2)
print(newArray) // prints: ["5", "6", "3", "4", "1", "2"]
let array: [String] = []
let newArray = array.reverseFlattenChunked(by: 3)
print(newArray) // prints: []
#2. Using stride(from:to:by:) and Sequence flatMap(_:)
extension Array {
func reverseFlattenChunked(by distance: Int) -> [Element] {
precondition(distance > 0, "distance must be greater than 0")
let indicesSequence = stride(from: self.endIndex, to: self.startIndex, by: -distance)
let array = indicesSequence.flatMap({ (index) -> SubSequence in
let advancedIndex = self.index(index, offsetBy: -distance, limitedBy: self.startIndex) ?? self.startIndex
// let advancedIndex = index.advanced(by: -distance) <= self.startIndex ? self.startIndex : index.advanced(by: -distance) // also works
return self[advancedIndex ..< index]
})
return array
}
}
Usage:
let array = ["1", "2", "3", "4", "5", "6", "7"]
let newArray = array.reverseFlattenChunked(by: 3)
print(newArray) // prints: ["5", "6", "7", "2", "3", "4", "1"]
let array: [String] = ["1", "2", "3", "4", "5", "6"]
let newArray = array.reverseFlattenChunked(by: 2)
print(newArray) // prints: ["5", "6", "3", "4", "1", "2"]
let array: [String] = []
let newArray = array.reverseFlattenChunked(by: 3)
print(newArray) // prints: []

Remove the first par of bracket from an Array Swift 3

I have this array with double pairs of bracket [["0": 5, "2": 10]] and I want to convert it to ["5","10"] or [5,10]
let dict = [["0": 5, "2": 10]]
let dict0 = dict[0]
var array: [Int] = []
array.append(dict0["0"]!)
array.append(dict0["2"]!)
This will do the trick. We're just extracting the dictionary values and creating an array. If you had a long list you could put your dictionary through a for-loop.
let dictionary = [["0": 5, "2": 10]]
let array = [dictionary[0]["0"]!,dictionary[0]["2"]!]
print("array: \(array)")
I don't know what you are trying to achieve here. But this solution does exactly what you asked in your question. i.e. convert an Array of Array of Dictionary into an Array ( [["0": 5, "2": 10]] -> [5,10] )
let data = [["0": 5, "2": 10]]
var finalArray = Array<Any>()
for dictArr in data {
for (key,value) in dictArr {
finalArray.append(value) //[5,10]
}
}
If you want to convert an Array of Array of Dictionary into an Array of Array of Element ( [["0": 5, "2": 10]] -> [[5,10]] ), use the following code.
let data = [["0": 5, "2": 10]]
var finalArray = Array<Any>()
for dictArr in data {
var tempArr = [Int]()
for (key,value) in dictArr {
tempArr.append(value)
}
finalArray.append(tempArr) //[[5,10]]
}

Removing objects from an array based on another array

I have two arrays like this:
var arrayA = ["Mike", "James", "Stacey", "Steve"]
var arrayB = ["Steve", "Gemma", "James", "Lucy"]
As you can see, James and Steve match and I want to be able to remove them from arrayA. How would I write this?
#francesco-vadicamo's answer in Swift 2/3/4+
arrayA = arrayA.filter { !arrayB.contains($0) }
The easiest way is by using the new Set container (added in Swift 1.2 / Xcode 6.3):
var setA = Set(arrayA)
var setB = Set(arrayB)
// Return a set with all values contained in both A and B
let intersection = setA.intersect(setB)
// Return a set with all values in A which are not contained in B
let diff = setA.subtract(setB)
If you want to reassign the resulting set to arrayA, simply create a new instance using the copy constructor and assign it to arrayA:
arrayA = Array(intersection)
The downside is that you have to create 2 new data sets.
Note that intersect doesn't mutate the instance it is invoked in, it just returns a new set.
There are similar methods to add, subtract, etc., you can take a look at them
Like this:
var arrayA = ["Mike", "James", "Stacey", "Steve"]
var arrayB = ["Steve", "Gemma", "James", "Lucy"]
for word in arrayB {
if let ix = find(arrayA, word) {
arrayA.removeAtIndex(ix)
}
}
// now arrayA is ["Mike", "Stacey"]
I agree with Antonio's answer, however for small array subtractions you can also use a filter closure like this:
let res = arrayA.filter { !contains(arrayB, $0) }
matt and freytag's solutions are the ONLY ones that account for duplicates and should be receiving more +1s than the other answers.
Here is an updated version of matt's answer for Swift 3.0:
var arrayA = ["Mike", "James", "Stacey", "Steve"]
var arrayB = ["Steve", "Gemma", "James", "Lucy"]
for word in arrayB {
if let ix = arrayA.index(of: word) {
arrayA.remove(at: ix)
}
}
Original answer
This can also be implemented as a minus func:
func -<T:RangeReplaceableCollectionType where T.Generator.Element:Equatable>( lhs:T, rhs:T ) -> T {
var lhs = lhs
for element in rhs {
if let index = lhs.indexOf(element) { lhs.removeAtIndex(index) }
}
return lhs
}
Now you can use
arrayA - arrayB
Updated implementation for Swift 5
func -<T: RangeReplaceableCollection>(lhs: T, rhs: T) -> T where T.Iterator.Element: Equatable {
var lhs = lhs
for element in rhs {
if let index = lhs.firstIndex(of: element) { lhs.remove(at: index) }
}
return lhs
}
Using the Array → Set → Array method mentioned by Antonio, and with the convenience of an operator, as freytag pointed out, I've been very satisfied using this:
// Swift 3.x/4.x
func - <Element: Hashable>(lhs: [Element], rhs: [Element]) -> [Element]
{
return Array(Set<Element>(lhs).subtracting(Set<Element>(rhs)))
}
For smaller arrays I use:
/* poormans sub for Arrays */
extension Array where Element: Equatable {
static func -=(lhs: inout Array, rhs: Array) {
rhs.forEach {
if let indexOfhit = lhs.firstIndex(of: $0) {
lhs.remove(at: indexOfhit)
}
}
}
static func -(lhs: Array, rhs: Array) -> Array {
return lhs.filter { return !rhs.contains($0) }
}
}
Remove elements using indexes array:
Array of Strings and indexes
let animals = ["cats", "dogs", "chimps", "moose", "squarrel", "cow"]
let indexAnimals = [0, 3, 4]
let arrayRemainingAnimals = animals
.enumerated()
.filter { !indexAnimals.contains($0.offset) }
.map { $0.element }
print(arrayRemainingAnimals)
//result - ["dogs", "chimps", "cow"]
Array of Integers and indexes
var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
let indexesToRemove = [3, 5, 8, 12]
numbers = numbers
.enumerated()
.filter { !indexesToRemove.contains($0.offset) }
.map { $0.element }
print(numbers)
//result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
Remove elements using element value of another array
Arrays of integers
let arrayResult = numbers.filter { element in
return !indexesToRemove.contains(element)
}
print(arrayResult)
//result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
Arrays of strings
let arrayLetters = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
let arrayRemoveLetters = ["a", "e", "g", "h"]
let arrayRemainingLetters = arrayLetters.filter {
!arrayRemoveLetters.contains($0)
}
print(arrayRemainingLetters)
//result - ["b", "c", "d", "f", "i"]

Resources