How to convert a String (numeric) in a Int array in Swift - arrays

I'd like to know how can I convert a String in an Int array in Swift.
In Java I've always done it like this:
String myString = "123456789";
int[] myArray = new int[myString.lenght()];
for(int i=0;i<myArray.lenght;i++){
myArray[i] = Integer.parseInt(myString.charAt(i));
}
Thanks everyone for helping!

let str = "123456789"
let intArray = map(str) { String($0).toInt() ?? 0 }
map() iterates Characters in str
String($0) converts Character to String
.toInt() converts String to Int. If failed(??), use 0.
If you prefer for loop, try:
let str = "123456789"
var intArray: [Int] = []
for chr in str {
intArray.append(String(chr).toInt() ?? 0)
}
OR, if you want to iterate indices of the String:
let str = "123456789"
var intArray: [Int] = []
for i in indices(str) {
intArray.append(String(str[i]).toInt() ?? 0)
}

You can use flatMap to convert the characters into a string and coerce the character strings into an integer:
Swift 2 or 3
let string = "123456789"
let digits = string.characters.flatMap{Int(String($0))}
print(digits) // [1, 2, 3, 4, 5, 6, 7, 8, 9]"
Swift 4
let string = "123456789"
let digits = string.flatMap{Int(String($0))}
print(digits) // [1, 2, 3, 4, 5, 6, 7, 8, 9]"
Swift 4.1
let digits = string.compactMap{Int(String($0))}
Swift 5 or later
We can use the new Character Property wholeNumberValue https://developer.apple.com/documentation/swift/character/3127025-wholenumbervalue
let digits = string.compactMap{$0.wholeNumberValue}

#rintaro's answer is correct, but I just wanted to add that you can use reduce to weed out any characters that can't be converted to an Int, and even display a warning message if that happens:
let str = "123456789"
let intArray = reduce(str, [Int]()) { (var array: [Int], char: Character) -> [Int] in
if let i = String(char).toInt() {
array.append(i)
} else {
println("Warning: could not convert character \(char) to an integer")
}
return array
}
The advantages are:
if intArray contains zeros you will know that there was a 0 in str, and not some other character that turned into a zero
you will get told if there is a non-Int character that is possibly screwing things up.

Swift 3
Int array to String
let arjun = [1,32,45,5]
print(self.get_numbers(array: arjun))
func get_numbers(array:[Int]) -> String {
let stringArray = array.flatMap { String(describing: $0) }
return stringArray.joined(separator: ",")
String to Int Array
let arjun = "1,32,45,5"
print(self.get_numbers(stringtext: arjun))
func get_numbers(stringtext:String) -> [Int] {
let StringRecordedArr = stringtext.components(separatedBy: ",")
return StringRecordedArr.map { Int($0)!}
}

var myString = "123456789"
var myArray:[Int] = []
for index in 0..<countElements(myString) {
var myChar = myString[advance(myString.startIndex, index)]
myArray.append(String(myChar).toInt()!)
}
println(myArray) // [1, 2, 3, 4, 5, 6, 7, 8, 9]"
To get the iterator pointing to a char from the string you can use advance
The method to convert string to int in Swift is toInt()

Swift 3 update:
#appzYourLife : That's correct toInt() method is no longer available for String in Swift 3.
As an alternative what you can do is :
intArray.append(Int(String(chr)) ?? 0)
Enclosing it within Int() converts it to Int.

Swift 3: Functional Approach
Split the String into separate String instances using:
components(separatedBy separator: String) -> [String]
Reference: Returns an array containing substrings from the String that have been divided by a given separator.
Use the flatMap Array method to bypass the nil coalescing while converting to Int
Reference: Returns an array containing the non-nil results of calling the given transformation with each element of this sequence.
Implementation
let string = "123456789"
let intArray = string.components(separatedBy: "").flatMap { Int($0) }

let array = "0123456789".compactMap{ Int(String($0)) }
print(array)

Related

How Can I convert byte array to String in Swift

I have a json as below. I need to convert the image to a byte array and post it as a String.
I can convert the image to byte array but how can I convert it to String?
I am getting an error while converting byte array to String.
Error:
"not a valid UTF-8 sequence"
JSON:
"photo1": "[255,216,255,224,0,16,74,70,73, ..... ,]"
Image Data to Byte Array:
func getArrayOfBytesFromImage(imageData:NSData) -> Array<UInt8> {
// the number of elements:
let count = imageData.length / MemoryLayout<Int8>.size
// create array of appropriate length:
var bytes = [UInt8](repeating: 0, count: count)
// copy bytes into array
imageData.getBytes(&bytes, length:count * MemoryLayout<Int8>.size)
var byteArray:Array = Array<UInt8>()
for i in 0 ..< count {
byteArray.append(bytes[i])
}
return byteArray
}
Using getArrayOfBytesFromImage Function:
if let string = String(bytes: getArrayOfBytesFromImage(imageData: imageData), encoding: .utf8) {
print(string)
} else {
print("not a valid UTF-8 sequence")
}
Those are not UTF-8 bytes, so don't say encoding: .utf8. Those bytes do not form a string, so you should not use String.init(bytes:encoding:). You should get the value of those bytes, and get their description one way or another (e.g. by string interpolation).
You don't even need a byte array here. Just go straight to strings, since that's what you're after.
let imageData = Data([1, 2, 3, 4, 5]) // for example
let string = "[\(imageData.map { "\($0)" }.joined(separator: ","))]"
print(string) // prints [1,2,3,4,5]

Not getting max element of array

I have a string array called prodIDArr having values like so...
["1","2","3","4","5","6","7","8","9","10"]
But when I do something like so..
let maxVal = prodIDArr.max()
I get the value of maxVal as 9 and not 10.
What could be the reason for this...?
That is an array of strings, and those are compared lexicographically:
"1" < "10" < "2" < ... < "9"
For example "10" < "2" because the initial characters already
satisfy "1" < "2". (For the gory details, see for example
What does it mean that string and character comparisons in Swift are not locale-sensitive?.)
Using an array of integers would be the best solution:
let prodIDArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let maxId = prodIDArr.max()
print(maxId) // Optional(10)
If that is not possible then you can enforce a numeric comparison with
let prodIDArr = ["1","2","3","4","5","6","7","8","9","10"]
let maxId = prodIDArr.max(by: { $0.compare($1, options: .numeric) == .orderedAscending })
print(maxId) // Optional("10")
You can also map your original String Array to an Int Array
let prodIDArr = ["1","2","3","4","5","6","7","8","9","10"]
let prodNumArray = prodIDArr.map { input in Int(input)!} // or { Int($0)! }
print(prodNumArray.max()!)

String into array in Swift 3

I am trying to transform a string of the following format into an array (...of arrays, of floats!) in Swift 3:
"[173.0, 180.5],[173.0, 180.0],[174.0, 180.5],[174.0, 183.0]"
so that the output would be an array in this format:
[[173.0, 180.5, 173.0, 180.0],[174.0, 180.5, 174.0, 183.0]]
I am really new to Swift and struggling to find any String functions that will allow me to convert the data in this way. Any pointers on how I can do it would be awesome - thanks!
As Martin said, you first want to first convert this from a string to an array. In Swift 3:
let string = "[173.0, 180.5],[173.0, 180.0],[174.0, 180.5],[174.0, 183.0]"
let jsonString = "[" + string + "]"
guard let data = jsonString.data(using: .utf8),
let json = try? JSONSerialization.jsonObject(with: data),
let numberPairs = json as? [[Double]] else {
fatalError("string was not well-formed: \(string)")
}
You then want to combine these pairs of numbers together:
var combinedNumbers = [[Double]]()
var current: [Double]?
for numberPair in numberPairs {
if current != nil {
combinedNumbers.append(current! + numberPair)
current = nil
} else {
current = numberPair
}
}
// use `combinedNumbers` here
Clearly, you should use better variable names (perhaps something that suggests what these sets of numbers are), but hopefully this illustrates the idea.
Swift 4
You can use Decodable:
let str = "[173.0, 180.5],[173.0, 180.0],[174.0, 180.5],[174.0, 183.0]"
let json = "[\(str)]".data(using: .utf8)!
let numbers = try JSONDecoder().decode([[Double]].self, from: json).flatMap { $0 }
let result = stride(from: 0, to: numbers.count, by: 4).map { startIndex -> [Double] in
let endIndex = min(startIndex + 4, numbers.count)
return Array(numbers[startIndex..<endIndex])
}
Swift 3
One option is to use the old-school NSScanner to extract the numbers from the string to a flat array, then build a 2 dimensional array off that:
let str = "[173.0, 180.5],[173.0, 180.0],[174.0, 180.5],[174.0, 183.0]"
let scanner = Scanner(string: str)
scanner.charactersToBeSkipped = CharacterSet(charactersIn: "[], ")
// Build the flat array
var numbers = [Double]()
while !scanner.isAtEnd {
var d = 0.0
if scanner.scanDouble(&d) {
numbers.append(d)
}
}
// Now the 2 dimensional array
let result = stride(from: 0, to: numbers.count, by: 4).map { startIndex -> [Double] in
let endIndex = min(startIndex + 4, numbers.count)
return Array(numbers[startIndex..<endIndex])
}
One option to convert the data types would be to develop a simple algorithm that will iterate through the string and analyze elements and square bracket delimiters, returning the appropriate conversion.
Below is the skeleton of what the fundamental components of such a function could look like.
Included are some basic aspects of the conversion from string to array.
var str = "[173.0, 180.5], [173.0, 180.0],[174.0, 180.5],[174.0, 183.0]"
// Cast returns array ["[","1","7","3",".","0",",".......]
let array = Array(str.characters)
// Iterate through array
for char in array {
if char == "[" || char == "]" {
// Deal with array delimiters appropriately
}
...
}
It might help to check out this similar problem.
NOTE: As Martin R mentioned, JSON interpretation may be a good method as well.

swift array storing data

I made a function that returns multiple values
let interestingNumbers = [ // String:Array<Int>
"Prime": [2, 3, 5, 7, 11, 23],
"Fibonacci": [1, 1, 2, 3, 5, 80],
"Square": [1, 4, 9, 16, 25],
]
func largestNum(objDictionary:[String:Array<Int>]) -> (Int,String) {
var largest = 0
var ki:String? = nil
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
ki=kind
}
}
}
return (largest , ki!)
}
print(largestNum(interestingNumbers)) //calling fuction and print
/*var ar2:[Int,String] = largestNum(interestingNumbers))
print(ar2)*/' this code have an error`
How can I store the returned values from the function in the array
Update:
If you want both values in a single array with ar[0] being the Int and ar[1] being the String, then you'll need to declare ar2 to be [Any] and unpack the tuple when initializing ar2:
let largest = largestNum(interestingNumbers)
var ar2:[Any] = [largest.0, largest.1]
print(ar2) // [80, "Fibonacci"]
If you just assign the return to ar2 and leave it as a tuple, you can access the values with ar2.0 and ar2.1:
var ar2 = largestNum(interestingNumbers)
print(ar2.0) // 80
print(ar2.1) // "Fibonacci"
Or if you change your largestNum to return a named tuple:
func largestNum(objDictionary:[String:Array<Int>]) -> (number: Int, kind: String) {
}
var ar2 = largestNum(interestingNumbers)
print(ar2.number) // 80
print(ar2.kind) // "Fibonacci"
Original Answer:
Declare your array ar2 to hold tuples pairs of Int and String, and then wrap your return value in [] to create an array:
var ar2:[(Int,String)] = [largestNum(interestingNumbers)]
print(ar2) // [(80, "Fibonacci")]
Because tuples are really meant for temporary values, it is better style to store values in an array using a struct:
Change your function to return an InterestingNumber:
struct InterestingNumber {
let kind: String
let number: Int
}
func largestNum(objDictionary:[String:Array<Int>]) -> InterestingNumber {
// contents omitted for brevity
return InterestingNumber(kind: ki!, number: largest)
}
let largest = largestNum(interestingNumbers)
// Define your array to hold `InterestingNumber`s:
var ar2:[InterestingNumber] = [largest]
print(ar2) // [InterestingNumber(kind: "Fibonacci", number: 80)]
If you meant for ar2 to just hold a single value, then simply do:
var ar2 = largestNum(interestingNumbers)
and Swift will infer the type (which is a tuple in your original code or an InterestingNumber when using the struct.
your code runs fine in xcode 7.3.1 playground
okay, now i get your question:
let z: (Int, String) = largestNum(interestingNumbers)
The part after the arrow in your function definition is the type (i think called tupel), you can use it for a variable.

Swift code: how do you build a Dictionary of Array of String based on Dictionary entry being nil

I have been trying to understand how to do some simple things with Swift using Dictionary and Array types.
I started by trying to write the simple functions below for manipulating a list of strings and bucketing them into the same array when the strings are anagrams of one another..!
Everything here should run in a playground on Xcode.
Questions:
Why can I not use toString() to convert Character Array to a String. I have to iterate over the Array of Character and build the string using += ?
What is the best way to add an Array to the Dictionary in the fly as I find that the Dictionary is empty for that string index so I need to create a new Array to hold the strings that sage the same letters. The confusion about a Dictionary not holding the types you think but actually holding Type? (that is Option Type - in my case String?, optional String).
See the crazy code below.
groupAnagrams(
listofWords: pass an array of String (immutable)
)
returns
Dictionary of Array of String (grouped anagrams)
A summary of numbers of actions taken in a Array of String
A log of actions taken in an Array of String
Purpose
Group the words that are anagrams together into buckets
The func will create a Dictonary indexed on a String that is the order string of characters, e.g.
["bats", "stab"] => [ "abst" : ["rats", "stab"] ]
Function charArrayToString
func charArrayToString(charArray ca: [Character]) -> String {
var s = ""
for c in ca {
s += String(c)
}
return s
}
func groupAnagrams(#listOfWords: [String]) -> [String:[String]] {
var s = ""
var d: [String:[String]] = [String:[String]]()
var i = 0, j = 0, k = 0
var log = [String]()
for s in listOfWords {
var s1:[Character] = [Character](s)
// var s1 = s
sort(&s1) { (a: Character, b: Character) -> Bool in return String(a) < String(b) }
//??? var s2 = toString(s1) // converts the Array of Character to a string (but it's for the for "[a,b,c,d]" and not "abcd" as you'd expect!
var s3 = charArrayToString(charArray: s1)
// Array already exists, add a string ELSE create the String array [String]() and add the fisst element
if let p = d[s3] {
// Array exists but d[s3] is "immutable" as it's optional array of String (type [String]?)
++i
var arr = d[s3]!
arr += [s]
d[s3] = arr
log += "Add string \(arr.count) \(s) to array \(s3) \n"
} else {
// ELSE: Create new String array
++j
d[s3] = [String]()
var arr = d[s3]!
arr += [s]
d[s3] = arr
log += "Create array for \(s3) with string \(s) \n"
}
++k
// break
}
var summary = [String]()
summary += ["\(i) strings added to already created arrays"]
summary += ["\(j) arrays created"]
summary += ["\(k) words processed"]
summary[0] // inspect
summary[1] // inspect
summary[2] // inspect
log // inspect
return d
}
// Same as the array version of the function but just adds stings to the paratner list of the function
func groupAnagramsList(strings: String...) -> [String:[String]] {
return groupAnagrams(listOfWords: strings)
}
Calls to the various functions created:
var listOfWords = [String]() + ["bats", "star", "tree", "stab", "rats", "reet", "pong", "peel", "leep", "path", "type", "pyte", "ypte"]
var anagrams = groupAnagrams(listOfWords: listOfWords)
var otherWay = groupAnagramsList("bats", "star", "tree", "stab", "rats", "reet", "pong", "peel", "leep", "path", "type", "pyte", "ypte")
UPDATE FROM Swift Beta 5:
if d[s3] == nil {
d[s3] = [String]()
++j
} else {
++i
}
d[s3]! += [s]
log += ["Add string \(d[s3]!.count) \(s) to array \(s3) \n"]
The check for nil on the Dictionary d is valid! In this context the complicated optional / immutable behavior is gone and the code is much easier to understand.
Note: I had to change
log += "Add string (d[s3]!.count) (s) to array (s3) \n"
To:
log += ["Add string (d[s3]!.count) (s) to array (s3) \n"]
Because you now need to explicitly add an Array of String to an Array of String. You cannot assume that += on a String will append a String to the Array. But it's easy, just wrap the string in '[' and ']'.
I still don't know why I cannot just cast a Character Array to a String!
Maybe a smart thing would be to use Swift's built-in Objective-C APIs to eliminate duplicate values. E.g:
let unique = NSSet(array: swiftArrayOfNonUniqueStrings).allObjects
The problem is, applying this to your character-sorted, duplicates-containing string array will just return the character-sorted version of your original string. (You can obtain such an array by returning alphaList below.)
As for sorting the characters within the string, I believe that iterating through the characters to build the string is efficient enough. You can write this a bit more succinctly
func alphabetizeStrings(list : [String]) -> [String] {
var newlist = [String]()
var alphaList = [String]()
for s in list {
var charArray = [Character](s)
charArray.sort({ (a: Character, b: Character) -> Bool in return String(a) < String(b)})
var sortedString = ""
for c in charArray {
sortedString += c
}
if NSArray(array: alphaList).containsObject(sortedString) == false {
newlist.append(s)
}
alphaList.append(sortedString)
}
return newlist
}
Thus:
let swiftarray = ["foo", "foo", "bar", "bra", "bat"]
let unique = alphabetizeStrings(swiftarray)
// ["foo", "bar", "bat"]

Resources