How to split an Int to its individual digits? - swift

I am trying to split an Int into its individual digits, e.g. 3489 to 3 4 8 9, and then I want to put the digits in an Int array.
I have already tried putting the number into a string and then iterating over each digit, but it doesn't work:
var number = "123456"
var array = [Int]()
for digit in number {
array.append(digit)
}
Any ideas?

We can also extend the StringProtocol and create a computed property:
edit/update: Xcode 11.5 • Swift 5.2
extension StringProtocol {
var digits: [Int] { compactMap(\.wholeNumberValue) }
}
let string = "123456"
let digits = string.digits // [1, 2, 3, 4, 5, 6]
extension LosslessStringConvertible {
var string: String { .init(self) }
}
extension Numeric where Self: LosslessStringConvertible {
var digits: [Int] { string.digits }
}
let integer = 123
let integerDigits = integer.digits // [1, 2, 3]
let double = 12.34
let doubleDigits = double.digits // // [1, 2, 3, 4]
In Swift 5 now we can use the new Character property wholeNumberValue
let string = "123456"
let digits = string.compactMap{ $0.wholeNumberValue } // [1, 2, 3, 4, 5, 6]

A solution without having to convert the int to string....
Example
1234%10 = 4 <-
1234/10 = 123
123%10 = 3 <-
123/10 = 12
12%10 = 2 <-
12/10 = 1
1%10 = 1 <-
var num = 12345
var arrayInt = [Int]()
arrayInt.append(num%10)
while num >= 10 {
num = num/10
arrayInt.insert(num%10, at: 0)
}

Swift 5
extension Int {
func digits() -> [Int] {
var digits: [Int] = []
var num = self
digits.append(num % 10)
while num >= 10 {
num = num / 10
digits.append(num % 10)
}
return digits.reversed()
}
}

You can try this:
var number = "123456"
var array = number.utf8.map{Int($0)-48}
You can make use of the utf8 property of String to directly access the ASCII value of the characters in the String representation of your number.

this code works:
var number = "123456"
var array = number.utf8.map{Int(($0 as UInt8)) - 48}
this might be slower:
var array = number.characters.map{Int(String($0))!}
and if your number is less or equal than Int.max which is 9223372036854775807 here is the fastest variant (and if your number>Int.max you can split your long string that represents your number into 18-digit groups to make this variant work on large strings)
var array2 = [Int]()
var i = Int(number)!
while i > 0 {array2.append(i%10); i/=10}
array2 = array2.reverse()

You can use this
extension Int {
func numberOfDigits() -> Int {
if abs(self) < 10 {
return 1
} else {
return 1 + (self/10).numberOfDigits()
}
}
func getDigits() -> [Int] {
let num = self.numberOfDigits()
var tempNumber = self
var digitList = [Int]()
for i in (0..<num).reversed() {
let divider = Int(pow(CGFloat(10), CGFloat(i)))
let digit = tempNumber/divider
digitList.append(digit)
tempNumber -= digit*divider
}
return digitList
}
}

if you need convert integer to Array
let num = 12345
let array = String(num).compactMap({$0.wholeNumberValue})
print("\(array), \(type(of: array))")
//[1,2,3,4,5], Array<Int>

extension Int {
var digits : [Int] {
var result = [Int]()
var remaining = abs(self)
while remaining > 0 {
result.insert(remaining % 10, at: 0)
remaining /= 10
}
return result
}
}

You can use this:
// input -> "123456"
// output -> [1, 2, 3, 4, 5, 6]
// Get the string, convert it in an Array(),
// use a loop (convert i in Int()), to add it into a container, then return it. Done!
func getDigitsFromString(for string: String) -> [Int]{
let stringInt = Array(string)
var array = [Int]()
for i in stringInt {
if let i = Int(String(i)) {
array.append(i)
}
}
return array
}

There is a simpler method to achieve this. Say x = 12345 , then
var s = String(x);
var numArray = Array(s);
clean, easy-to-read code.

You can use:
let number = -123
let regex = /-?\d/
let values = String(number).matches(of: regex).compactMap { Int($0.output) }
print(values) // [-1, 2, 3]
This code takes into account negative values

Related

Cannot mupliply Int by 2 in Swift

I have an array of digits presented like strings - ["1", "2", "3"]
my goal is to return back the multiplied array.
func multiplyInts(_ num: Int) -> Array<Any> {
var arr = Array(String(num))
var resultArr = [Int]()
for i in 0...arr.count {
var strIn = String(arr[i])
var numIn = Int(strIn) * 2 // here's the error
resultArr.append(numIn)
}
return Array(resultArr)
}
I'm converting String to Int and multiplying this number by two, but my program won't compile and says error.
Basically there are at least two displayed errors and a fatal mistake.
The return type is wrong
Int(strIn) returns an optional, you have to (safely) unwrap it
0...arr.count will cause a crash, it must be 0..<arr.count
Further
the parameter type should be [String]
Creating an Array from an Array is redundant.
Long story short: To convert a string array to an Int array and multiply each element by two you can use this
func multiplyInts(_ array: [String]) -> [Int] {
return array.compactMap(Int.init).map{$0 * 2}
}
let result = multiplyInts(["1", "2", "3"]) // [2, 4, 6]
Below code may be useful for you
func multiplyInts(_ num: Int) -> Array<Any> {
let arr = Array(String(num))
var resultArr = [Int]()
for i in 0..<arr.count {
let strIn = String(arr[i])
if let intNum = Int(strIn) {
let numIn = intNum * 2
resultArr.append(numIn)
}
}
return Array(resultArr)
}
print(multiplyInts(123)) // [2, 4, 6]
Just use map.
func multiplyInts(_ num: [Int]) -> [Int] {
num.map { $0 * 2 }
}
Example:
print(multiplyInts([1, 2, 3]))
// Prints: [2, 4, 6]

How to count the individual elements in an array?

I want to count the individual elements in the following array:
let b = [
1, 2, 3,
[4,5,6],
[
[7,8],
[9,0]
]
]
, and I was able to count the following array:
let a = [
[1,2,3],
[4,5],
[6,7,8,9]
]
with the following code:
protocol DeepCountable {
var deepCount: Int {get}
}
// conditional conformance
extension Array: DeepCountable where Element: DeepCountable {
var deepCount: Int {
return self.reduce(0){$0 + $1.deepCount}
}
}
extension Int: DeepCountable {
var deepCount: Int { return 1 }
}
print(a.deepCount) // 9
How do I do the same thing to array b?
print( b.deepCount )
Type of array b is [Any]. Any isn't DeepCountable. Now add a deepcount property in Array
extension Array: DeepCountable {
var deepCount: Int {
return self.compactMap({ $0 as? DeepCountable }).reduce(0, { $0 + $1.deepCount })
}
}
let a = [[1,2,3],[4,5],[6,7,8,9]]
print(a.deepCount)//9
let b = [1, 2, 3,[4,5,6],[[7,8],[9,0]]] as [Any]
print(b.deepCount)//10
let c = [1,2,"a","b"] as [Any]
print(c.deepCount)//2
Here is a generic solution that can count different types
extension Array {
func countType<T>(_ elemType: T.Type) -> Int {
var count = 0
for elem in self {
if let _ = elem as? T {
count += 1
} else if let arr = elem as? [Any] {
count += arr.countType(elemType)
}
}
return count
}
}
Usage
let b = [1, 2, 3,[4,5,6],[[7,8],[9,0]]] as [Any]
let c = [1,2,"a","b"] as [Any]
print("Int Count \(b.countType(Int.self))")
print("Array Count \(b.countType([Int].self))")
print("Int Count \(c.countType(Int.self))")
print("String Count \(c.countType(String.self))")
print("Array Count \(c.countType([Int].self))")
yields
Int Count 10
Array Count 3
Int Count 2
String Count 2
Array Count 0
Firstly you need to flatten the array into single then count that array.
let b = [
1, 2, 3,
[4,5,6],
[
[7,8],
[9,0]
]
]
let flatb = b.flatMap({ $0 })
print(flatb.count)
The following code is the result I concluded from the above contributions:
protocol DeepCountable {
var deepCount: Int { get }
}
// now any Array is DeepCountable
extension Array: DeepCountable {
var deepCount: Int {
return compactMap{ $0 as? DeepCountable }.reduce(0){ $0 + $1.deepCount }
}
}
extension Int: DeepCountable {
var deepCount: Int { return 1 }
}
// test
let a = [[1,2,3],[4,5],[6,7,8,9]]
let b = [1, 2, 3,[4,5,6],[[7,8],[9,0]]] as [Any]
let c = [1,2,"a","b"] as [Any]
let d = [1,2,3,[4,5],[6,7,8,[9, 0]]] as [Any]
print( a.deepCount ) // 9
print( b.deepCount ) // 10
print( c.deepCount ) // 2
print( d.deepCount ) // 10
This code should work with Swift 5, I've tried it on Online Swfit Playground, and it works fine.

How to read values of SparseMatrix_Double in Swift 4?

How do I write a function for printing out the contents of SparseMatrix_Double for Swift 4?
I have the following code so far, however, the output is only correct some of the time.
Sometimes the array is accessing memory that's out of range giving [[1.06540896337e-313, 0.0], [0.0, 3.0]]
I suspect that the way I obtain the number of nonzeros is wrong.
import Accelerate
func toString(_ A: SparseMatrix_Double) throws -> String {
if A.structure.rowCount > 100 || A.structure.columnCount > 100 {
print("Matrix is too big to display")
throw NSError(domain: "Matrix is too big to display", code: -1, userInfo: nil)
}
let rows = Int(A.structure.rowCount)
let columns = Int(A.structure.columnCount)
let nonzeros = A.structure.columnStarts[columns]
print("Row indices")
for i in 0..<nonzeros {
print("\(i): \(A.structure.rowIndices[i])")
}
print("Column starts")
for c in 0...columns {
print("\(c): \(A.structure.columnStarts[c])")
}
var M = Array(repeating: Array(repeating: 0.0, count: columns), count: rows)
var i = 0
var currentColumn: Int = 0
var nextColStarts = A.structure.columnStarts[1]
while currentColumn < (columns - 1) {
if i == nextColStarts {
currentColumn += 1
nextColStarts = A.structure.columnStarts[currentColumn + 1]
}
let rowIndex = Int(A.structure.rowIndices[i])
M[rowIndex][currentColumn] = A.data[i]
print("Setting \(rowIndex),\(currentColumn) [\(i)]")
i += 1
}
return M.description
}
var rows: [Int32] = [1]
var columns: [Int32] = [1]
var values: [Double] = [3.0]
let blockSize: UInt8 = 1
let blockCount = 8
let A = SparseConvertFromCoordinate(
2, 2,
blockCount, blockSize,
SparseAttributes_t(),
&rows, &columns,
&values
)
print(try? toString(A))

Reverse Strings without using predefined functions

Pardon me as I am a newbie on this language.
Edit: Is there a way to reverse the position of a array element?
I am trying to create a function that test the given input if its a palindrome or not. I'm trying to avoid using functions using reversed()
let word = ["T","E","S","T"]
var temp = [String]()
let index_count = 3
for words in word{
var text:String = words
print(text)
temp.insert(text, atIndex:index_count)
index_count = index_count - 1
}
Your approach can be used to reverse an array. But you have to
insert each element of the original array at the start position
of the destination array (moving the other elements to the end):
// Swift 2.2:
let word = ["T", "E", "S", "T"]
var reversed = [String]()
for char in word {
reversed.insert(char, atIndex: 0)
}
print(reversed) // ["T", "S", "E", "T"]
// Swift 3:
let word = ["T", "E", "S", "T"]
var reversed = [String]()
for char in word {
reversed.insert(char, at: 0)
}
print(reversed) // ["T", "S", "E", "T"]
The same can be done on the characters of a string directly:
// Swift 2.2:
let word = "TEST"
var reversed = ""
for char in word.characters {
reversed.insert(char, atIndex: reversed.startIndex)
}
print(reversed) // "TSET"
// Swift 3:
let word = "TEST"
var reversed = ""
for char in word.characters {
reversed.insert(char, at: reversed.startIndex)
}
print(reversed)
Swift 5
extension String {
func invert() -> String {
var word = [Character]()
for char in self {
word.insert(char, at: 0)
}
return String(word)
}
}
var anadrome = "god"
anadrome.invert()
// "dog"
Here's my solution:
extension String {
func customReverse() -> String {
var chars = Array(self)
let count = chars.count
for i in 0 ..< count/2 {
chars.swapAt(i, count - 1 - i)
}
return String(chars)
}
}
let input = "abcdef"
let output = input.customReverse()
print(output)
You can try it here.
func reverse(_ str: String) -> String {
let arr = Array(str) // turn the string into an array of all of the letters
let reversed = ""
for char in arr {
reversed.insert(char, at: reversed.startIndex)
}
return reversed
}
To use it:
let word = "hola"
let wordReversed = reverse(word)
print(wordReversed) // prints aloh
Another solution for reversing:
var original : String = "Test"
var reversed : String = ""
var c = original.characters
for _ in 0..<c.count{
reversed.append(c.popLast()!)
}
It simply appends each element of the old string that is popped, starting at the last element and working towards the first
Solution 1
let word = "aabbaa"
let chars = word.characters
let half = chars.count / 2
let leftSide = Array(chars)[0..<half]
let rightSide = Array(chars.reverse())[0..<half]
let palindrome = leftSide == rightSide
Solution 2
var palindrome = true
let chars = Array(word.characters)
for i in 0 ..< (chars.count / 2) {
if chars[i] != chars[chars.count - 1 - i] {
palindrome = false
break
}
}
print(palindrome)
static func reverseString(str : String) {
var data = Array(str)
var i = 0// initial
var j = data.count // final
//either j or i for while , data.count/2 buz only half we need check
while j != data.count/2 {
print("befor i:\(i) j:\(j)" )
j = j-1
data.swapAt(i, j) // swapAt API avalible only for array in swift
i = i+1
}
print(String(data))
}
//Reverse String
let str = "Hello World"
var reverseStr = ""
for char in Array(str) {
print(char)
reverseStr.insert(char, at: str.startIndex)
}
print(reverseStr)

What's the best way to cut Swift string into 2-letter-strings?

I need to split a string into 2-letter pieces. Like “friend" -> "fr" "ie" "nd". (Okay, its a step for me to change HEX string to Uint8 Array)
My code is
for i=0; i<chars.count/2; i++ {
let str = input[input.startIndex.advancedBy(i*2)..<input.startIndex.advancedBy(i*2+1)]
bytes.append(UInt8(str,radix: 16)!)
}
But I don't know why I cannot use Range to do this split. And I have no idea what will happen when i*2+1 is bigger than string's length. So what's the best way to cut Swift string into 2-letter-strings?
Your range wasn't working because you need to use ... instead of ..<.
let input = "ff103"
var bytes = [UInt8]()
let strlen = input.characters.count
for i in 0 ..< (strlen + 1)/2 {
let str = input[input.startIndex.advancedBy(i*2)...input.startIndex.advancedBy(min(strlen - 1, i*2+1))]
bytes.append(UInt8(str,radix: 16) ?? 0)
}
print(bytes) // [255, 16, 3]
Here is another take on splitting the string into 2-letter strings. advancedBy() is an expensive O(n) operation, so this version keeps track of start and just marches it ahead by 2 each loop, and end is based on start:
let input = "friends"
var strings = [String]()
let strlen = input.characters.count
var start = input.startIndex
let lastIndex = strlen > 0 ? input.endIndex.predecessor() : input.startIndex
for i in 0 ..< (strlen + 1)/2 {
start = i > 0 ? start.advancedBy(2) : start
let end = start < lastIndex ? start.successor() : start
let str = input[start...end]
strings.append(str)
}
print(strings) // ["fr", "ie", "nd", "s"]
Alternate Answer:
Using ranges is probably overkill. It is easy just to add the characters to an array and make Strings from those:
let input = "friends"
var strings = [String]()
var newchars = [Character]()
for c in input.characters {
newchars.append(c)
if newchars.count == 2 {
strings.append(String(newchars))
newchars = []
}
}
if newchars.count > 0 {
strings.append(String(newchars))
}
print(strings) // ["fr", "ie", "nd", "s"]
And here is the new version for making [UInt8]:
let input = "ff103"
var bytes = [UInt8]()
var newchars = [Character]()
for c in input.characters {
newchars.append(c)
if newchars.count == 2 {
bytes.append(UInt8(String(newchars), radix: 16) ?? 0)
newchars = []
}
}
if newchars.count > 0 {
bytes.append(UInt8(String(newchars), radix: 16) ?? 0)
}
print(bytes) // [255, 16, 3]
Based on #LeoDabus' answer, we can make an extension with a method that will return substrings of any length, and a computed property that returns [UInt8]:
extension String {
func substringsOfLength(length: Int) -> [String] {
if length < 1 { return [] }
var result:[String] = []
let chars = Array(characters)
for index in 0.stride(to: chars.count, by: length) {
result.append(String(chars[index ..< min(index+length, chars.count)]))
}
return result
}
var toUInt8: [UInt8] {
var result:[UInt8] = []
let chars = Array(characters)
for index in 0.stride(to: chars.count, by: 2) {
let str = String(chars[index ..< min(index+2, chars.count)])
result.append(UInt8(str, radix: 16) ?? 0)
}
return result
}
}
let input = "friends"
let str2 = input.substringsOfLength(2) // ["fr", "ie", "nd", "s"]
let str0 = input.substringsOfLength(0) // []
let str3 = input.substringsOfLength(3) // ["fri", "end", "s"]
let bytes = "ff107".toUInt8 // [255, 16, 7]
Another option just for fun:
extension String {
var pairs:[String] {
var result:[String] = []
let chars = Array(characters)
for index in 0.stride(to: chars.count, by: 2) {
result.append(String(chars[index..<min(index+2, chars.count)]))
}
return result
}
}
let input = "friends"
let pairs = input.pairs
print(pairs) // ["fr", "ie", "nd", "s"]