Converting Character in an array to an Integer - ios

I can't seem to figure out how to do this even though I've searched through documentation.
I'm trying to figure out how to convert a character at an index in an array to an integer.
For example, say I have a character array named "container", I can't figure out how to do:
var number:Integer = container[3]
Thanks for the help!

Swift doesn't make it easy to convert between primitive and typed representations of things. Here's an extension that should help in the meantime:
extension Character {
func utf8Value() -> UInt8 {
for s in String(self).utf8 {
return s
}
return 0
}
func utf16Value() -> UInt16 {
for s in String(self).utf16 {
return s
}
return 0
}
func unicodeValue() -> UInt32 {
for s in String(self).unicodeScalars {
return s.value
}
return 0
}
}
This allows you to get pretty close to what you want:
let container : Array<Character> = [ "a", "b", "c", "d" ]
/// can't call anything here, subscripting's also broken
let number = container[2]
number.unicodeValue() /// Prints "100"
For any engineers that come across this question, see rdar://17494834

I am not sure that it is effective or not but at least it worked. I converted Character to String then to Int.
String(yourCharacterInArray).toInt()

You may try this:
var container = "$0123456789"
var number:Int = Array(container.utf8).map { Int($0) }[3]
It's totally ugly, but it does the job. Also it is a bit computational expensive (O(n) each time one access a character in a string). Still this can be a trick to get back a way to build the CStrings:
typealias CString = Array<CChar>
func toCString(string: String) -> CString {
return Array(string.utf8).map { CChar($0) } + [0]
}
var cString = toCString("$ 0123456789")
println("The 2nd character in cString has value \(cString[1])") // It outputs 32
or without implementing a function:
var container = "$ 0123456789"
var containerAsCString = Array(container.utf8).map { CChar($0) } + [0]
println("The 2nd character in container has value \(containerAsCString[1])") // It outputs 32

Why not just for loop the array and convert everything to Int?
https://developer.apple.com/Library/mac/documentation/General/Reference/SwiftStandardLibraryReference/index.html

Why not just convert the character to String, get the unicodeScalars for it and extract the .value on the scalar?
something like:
var chr: [Character] = ["C", "B", "A"]
for a in String(chr[1]).unicodeScalars {
println(a.value)}

For me worked something like:
"\(container[3])".toInt()

Related

How to sort an array both numerically and alphabetically in Swift

Say I have an array:
var array = ["5C", "4D", "2H", "13S", "4C", "5H"]
How would I be able to sort this array so that the new array would have the last character sorted alphabetically, then the previous numerical values sorted numerically such as:
["4C", "5C", "4D", "2H", "5H", "13S"]
I am relatively new to coding in general and have a very basic grasp of syntax. Other searches have shown me how to sort numerically using the .sorted function and .ascendingOrder, but I couldn't find a solution that could sort both alphabetically and numerically.
EDIT:
My answer shows how to use sorted() to sort an array of strings into "numeric" order. It is not quite what the OP asked.
To the OP: You should accept vadian's answer. His was the first correct answer.
However, I spend some time in my answer explaining Swift closure syntax, so I am going to leave the answer.
You can use the array method sorted(), which takes a closure that compares pairs of objects and returns true if the first item should come first.
Then you can use the NSString method compare(options:) to do a "numeric" string comparison, where sequences of digits are treated as numbers inside the string.
Here is a working code snippet that will sort your array:
var array = ["5C", "4D", "2H", "13S", "4C", "5H"]
let sorted = array.sorted (by: { (first: String, second: String) -> Bool in
return first.compare(second, options: .numeric) == .orderedAscending
})
The function sorted() is a "higher order function`, or a function that takes another function as a parameter. For an array of strings, that function takes 2 strings, and returns a Bool. It actually takes a closure rather than a function, where a closure is an "anonymous function" (a function with no name.)
Adapting vadian's code that gives the CORRECT answer to my snippet, it would look like this:
var array = ["5C", "4D", "2H", "13S", "4C", "5H"]
let sorted = array.sorted (by: { (first: String, second: String) -> Bool in
if first.suffix(1) == second.suffix(1) {
return first.dropLast.compare(second, options: .numeric) == .orderedAscending
} else {
return first.suffix(1) < second.suffix(1)
}
})
You can rewrite the above with several shortcuts:
With a "trailing closure" you skip the () that contains the closure as a parameter and just provide the closure in braces after the function name.
You can skip the declaration of the parameters and return type of the closure, and skip the return statement:
let sorted = array.sorted { $0.compare($1, options: .numeric) == .orderedAscending }
For more complex code like vadian's that gives the correct answer, I suggest not using positional parameters like that. Using local variables like first and second make the code easier to read.
I suggest studying the chapter on Closures in Apple's Swift iBooks carefully until you understand the various ways that closures can be expressed and their different shortcut syntaxes. It's confusing at first, and using closures is fundamental to using Swift.
You have to write your own comparator which is pretty handy in Swift.
If the last character is the same sort the string without the last character numerically otherwise sort by the last character
let array = ["5C", "4D", "2H", "13S", "4C", "5H"]
let sortedArray = array.sorted { (str1, str2) -> Bool in
if str1.suffix(1) == str2.suffix(1) {
return str1.dropLast().localizedStandardCompare(str2.dropLast()) == .orderedAscending
} else {
return str1.suffix(1) < str2.suffix(1)
}
}
// ["4C", "5C", "4D", "2H", "5H", "13S"]
Welcome to StackOverflow!
What do these numbers represent? I would create a struct to model that "thing" (I'll call it Thing for now), and function that can parse a String into a Thing, like so:
struct Thing: Equatable { // FIXME: Name me something descriptive
let number: Int // FIXME: Name me something descriptive
let letter: Character // FIXME: Name me something descriptive
static func parse(from string: String) -> Thing? {
let numberSegment = string.prefix(while: { $0.isNumber })
guard !numberSegment.isEmpty,
let number = Int(numberSegment) else { return nil }
let letterSegement = string.drop(while: { $0.isNumber })
guard letterSegement.count == 1,
let letter = letterSegement.first else { return nil }
return Thing(number: number, letter: letter)
}
}
Then, you can just conform to Comparable, defining how you want things to be sorted, by defining the comparison operator <:
extension Thing: Comparable {
static func < (lhs: Thing, rhs: Thing) -> Bool {
return (lhs.letter, lhs.number) < (rhs.letter, rhs.number)
}
}
From there, it's just a matter of parsing all your strings into Things, and sorting them:
let array = ["5C", "4D", "2H", "13S", "4C", "5H"]
let things = array.map { Thing.parse(from: $0)! }
print("Before sorting:")
things.forEach { print("\t\($0)") }
let sortedThings = things.sorted()
print("\nAfter sorting:")
sortedThings.forEach { print("\t\($0)") }
Output:
Before sorting:
Thing(number: 5, letter: "C")
Thing(number: 4, letter: "D")
Thing(number: 2, letter: "H")
Thing(number: 13, letter: "S")
Thing(number: 4, letter: "C")
Thing(number: 5, letter: "H")
After sorting:
Thing(number: 4, letter: "C")
Thing(number: 5, letter: "C")
Thing(number: 4, letter: "D")
Thing(number: 2, letter: "H")
Thing(number: 5, letter: "H")
Thing(number: 13, letter: "S")
Welcome to StackOverflow!
this is my solution hope it works for you, I just organize first the numbers and next comparate with the alphabeth to create a new array:
var array = ["5C", "4D", "2H", "13S", "4C", "5H"]
array = array.sorted { $0.numbersValues < $1.numbersValues }
let str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var newArrray: [String] = []
for letter in str {
for value in array {
if value.lettersValues.hasPrefix(String(letter)) {
newArrray.append(value)
}
}
}
Don't forget include this helpers methods in your project
extension String {
var lettersValues: String {
return self.components(separatedBy: CharacterSet.decimalDigits).joined()
}
var numbersValues: String {
return self.filter { "0"..."9" ~= $0 }
}
}

Conditional map function in Swift

I'm taking an array of ([(String?, String)]) and want to drop the last 3 or 5 elements of the non-optional String, depending on the String.
If I know I'm dropping 5 I use
let strippedName = (data.map{ ($0.1).dropLast(5) } ).map{ String($0) }
however, as I said this is a conditional thing depending on the string within the array.
When I try
let strippedName = (data.map{
if ($0.1 == "a") {
return $0.1.first!
} else {
return $0.1.last!
}
} ).map{ String($0) }
(which is obviously not quite the finished article for my needs).
The example will crash on some inputs, that is irrelevant. I need to have an if statement in the map above (the detail of the if statement is not relevant). An alternative is any way to have a conditional map function in Swift (as is the question title).
As above, my requirement is "I'm taking an array of ([(String?, String)]) and want to drop the last 3 or 5 elements of the non-optional String, depending on the String."
I get an error on the last String() cast - Ambiguous use of init.
How can I take my array and use an if statement within my first map?
Another way to solve it is to use reduce
let strippedName = data.reduce(into: []) { if $1.1 == "a" {$0.append($1.1)}}
Update
Trying to solve this as OP wants by using an if in the mapping. For my example here I use compactMap rather than map, this way anything that doesn't satisfy the if condition will be excluded from the array.
Since the return type of the closure is define to be String I don't need to do a second mapping
let strippedName = data.compactMap { t -> String? in
if t.1 == "a" {
return t.1
}
return nil
}
Swift could not infer the complex closure return type, hence it is showing you the error "Ambiguous use of init()"
Specifying the return type explicitly solves the issue.
let data: [(String?, String)] = [("a","bBCDEA"), ("b","a"), (nil,"CBCDEB"), ("d","aBCDEF"), (nil,"a"), ("f","FBCDEC")]
var strippedName = (data.map { tuple -> String.Element in
if (tuple.1 == "a") {
return tuple.1.first!
} else {
return tuple.1.last!
}
}).map{ String($0) }
print(strippedName) // ["A", "a", "B", "F", "a", "C"]
strippedName = (data.map{ ($0.1).dropLast(5) } ).map{ String($0) }
print(strippedName) // ["b", "", "C", "a", "", "F"]
I think the problem is with anonimous closure and type inference, however, to get what you're trying in your second chunk of code, you can use filter instead of conditionals. With this you won't get error:
let strippedName = data.filter { $0.1 == "a" }.map { $0.1 }
and you can add dropLast to the end.

Splitting a Swift String using a multi-Character String in Swift 2

I understand that I can fallback to the NSString function componentsSeparatedByString, and so perhaps this is a nitpick, but one of the things I like about Swift is that it is designed around brevity and short syntax.
I was really hoping I could just: var parts = myString.characters.split("${") but that function only works for a single Character, not a two Character string. I even tried var parts = myString.characters.split { $0 == "${" } but that is expecting a single Character as the delimiter and not a full String. :(
Is there an api function that I'm missing or do I need to stick with the the old NSString bridged functions?
Here's a rather simple-minded approach that makes it possible to use Swift split on a single character:
extension String {
mutating func replace(target:String, with:String) {
while let r = self.rangeOfString(target) {
self.replaceRange(r, with: with)
}
}
func split(separator:String) -> Array<String> {
var s = self
s.replace(separator, with:"☞") // arbitrary improbable character :)
return s.characters.split("☞").map{String($0)}
}
}
var s = "the${cat${sat${on${the${mat"
let arr = s.split("${")
However, rangeOfString is actually a Foundation method on NSString; if you don't import Foundation (or UIKit), that code won't compile. So in reality it's no improvement over just calling componentsSeparatedByString. I don't actually understand your objection to it in the first place; Swift has holes exactly because it expects Foundation to be backing it up and filling those holes.
'pure' Swift's solution where import Foundation is NOT required and arbitrary improbable character doesn't exists
let str = "t{he${cat${sat${on${the${mat"
let splitBy = "${"
extension String {
func split(splitBy: String)->[String] {
if self.isEmpty { return [] }
var arr:[String] = []
var tmp = self
var tmp1 = ""
var i = self.startIndex
let e = self.endIndex
let c = splitBy.characters.count
while i < e {
let tag = tmp.hasPrefix(splitBy)
if !tag {
tmp1.append(tmp.removeAtIndex(tmp.startIndex))
i = i.successor()
} else {
tmp.removeRange(Range(start: tmp.startIndex, end: tmp.startIndex.advancedBy(c)))
i = i.advancedBy(c)
arr.append(tmp1)
tmp1 = ""
}
}
arr.append(tmp1)
return arr.filter{ !$0.isEmpty }
}
}
let arr = str.split(splitBy) // ["t{he", "cat", "sat", "on", "the", "mat"]
If you have Foundation imported, you can use the components(separatedBy:) method to accomplish that.
let str = "Foo, Bar, Baz"
str.components(separatedBy: ", ")
Here are the docs.
(Tested on Ubuntu Linux)

fastest indexOf function for strings

I am currently using following extension for a string to get the index for a specific string in a big string:
func indexOf(target: String, startIndex: Int) -> Int
{
var startRange = advance(self.startIndex, startIndex)
var range = self.rangeOfString(target, options: NSStringCompareOptions.LiteralSearch, range: Range<String.Index>(start: startRange, end: self.endIndex))
if let range = range {
return distance(self.startIndex, range.startIndex)
} else {
return -1
}
}
I am calling this many times and I have a performance issue.
Does anyone have an idea how to do the indexOf() faster ?
Currently I am doing this in swift. Will doing this in Objective-C and bridging give a better performance ? Or probably if possible include any C Code ? Any ideas ?
UPDATE more about the Background
I have a long text, say with 5000 characters.
The Text contains several Metadata tags beside from normal text. These Tags are like {{blabl{{ sdasdg }} abla}} ; [[bla bla|blabla]] ; {|bla|}.
I like to remove them or format them in a specific way.
I can't use regular expression for this, because regular expression does not support stacked expressions ({{ {{ {{ {{dsgasdg}} }}}} }} )
So I wrote my own functions, which works, but is very slow.
What I am actually doing is I go throught the text and I am simply searchiong for these tags. For this I need a base function like the following, to determine which tag is the first and at which position. When I found a tag I will go to the next and so on. I recognized, that this is my most timeconsuming part of all. Of course I am calling this also a lot of time.
func getStart(sText:String, alSearchPatterns:[String], ifrom:Int) -> (Pattern:String, index:Int) {
var bweiter:Bool=true;
var actualcharacter:Character;
var returnPattern="";
var returnIndex = -1;
println("ifrom : " + String(ifrom));
var indexfound:Int = -1;
// finde ersten character der Patterns
var bsuchepattern=true;
for(var i=0;i<alSearchPatterns.count && bsuchepattern;i++){
let sPattern=alSearchPatterns[i];
let pattern_first_char=sPattern[0];
//let pattern_first_char=String(sPattern[0]);
let characterIndex = sText.indexOfCharacter(pattern_first_char, fromIndex: ifrom); // find(sText, pattern_first_char);
//let characterIndex = sText.indexOf(pattern_first_char, startIndex: ivon);
if(characterIndex != -1){
if((indexfound == -1) || characterIndex < indexfound){
// found something that is first of all actually.
let patternlength=sPattern.length;
let substring_in_text=sText.substring(characterIndex, endIndex: characterIndex + patternlength);
if(substring_in_text.equals(sPattern)){
returnPattern=sPattern;
returnIndex=characterIndex;
}
}
}
}
return (returnPattern,returnIndex);
}
Any hints how to do this more performant or any hints on how to do this better in general.

Find Object with Property in Array

is there a possibility to get an object from an array with an specific property? Or do i need to loop trough all objects in my array and check if an property is the specific i was looking for?
edit: Thanks for given me into the correct direction, but i have a problem to convert this.
// edit again: A ok, and if there is only one specific result? Is this also a possible method do to that?
let imageUUID = sender.imageUUID
let questionImageObjects = self.formImages[currentSelectedQuestion.qIndex] as [Images]!
// this is working
//var imageObject:Images!
/*
for (index, image) in enumerate(questionImageObjects) {
if(image.imageUUID == imageUUID) {
imageObject = image
}
}
*/
// this is not working - NSArray is not a subtype of Images- so what if there is only 1 possible result?
var imageObject = questionImageObjects.filter( { return $0.imageUUID == imageUUID } )
// this is not working - NSArray is not a subtype of Images- so what if there is only 1 possible result?
You have no way to prove at compile-time that there is only one possible result on an array. What you're actually asking for is the first matching result. The easiest (though not the fastest) is to just take the first element of the result of filter:
let imageObject = questionImageObjects.filter{ $0.imageUUID == imageUUID }.first
imageObject will now be an optional of course, since it's possible that nothing matches.
If searching the whole array is time consuming, of course you can easily create a firstMatching function that will return the (optional) first element matching the closure, but for short arrays this is fine and simple.
As charles notes, in Swift 3 this is built in:
questionImageObjects.first(where: { $0.imageUUID == imageUUID })
Edit 2016-05-05: Swift 3 will include first(where:).
In Swift 2, you can use indexOf to find the index of the first array element that matches a predicate.
let index = questionImageObjects.indexOf({$0.imageUUID == imageUUID})
This is bit faster compared to filter since it will stop after the first match. (Alternatively, you could use a lazy sequence.)
However, it's a bit annoying that you can only get the index and not the object itself. I use the following extension for convenience:
extension CollectionType {
func find(#noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Generator.Element? {
return try indexOf(predicate).map({self[$0]})
}
}
Then the following works:
questionImageObjects.find({$0.imageUUID == imageUUID})
Yes, you can use the filter method which takes a closure where you can set your logical expression.
Example:
struct User {
var firstName: String?
var lastName: String?
}
let users = [User(firstName: "John", lastName: "Doe"), User(firstName: "Bill", lastName: "Clinton"), User(firstName: "John", lastName: "Travolta")];
let johns = users.filter( { return $0.firstName == "John" } )
Note that filter returns an array containing all items satisfying the logical expression.
More info in the Library Reference
Here is a working example in Swift 5
class Point{
var x:Int
var y:Int
init(x:Int, y:Int){
self.x = x
self.y = y
}
}
var p1 = Point(x:1, y:2)
var p2 = Point(x:2, y:3)
var p3 = Point(x:1, y:4)
var points = [p1, p2, p3]
// Find the first object with given property
// In this case, firstMatchingPoint becomes p1
let firstMatchingPoint = points.first{$0.x == 1}
// Find all objects with given property
// In this case, allMatchingPoints becomes [p1, p3]
let allMatchingPoints = points.filter{$0.x == 1}
Reference:
Trailing Closure
Here is other way to fetch particular object by using object property to search an object in array.
if arrayTicketsListing.contains({ $0.status_id == "2" }) {
let ticketStatusObj: TicketsStatusList = arrayTicketsListing[arrayTicketsListing.indexOf({ $0.status_id == "2" })!]
print(ticketStatusObj.status_name)
}
Whereas, my arrayTicketsListing is [TicketsStatusList] contains objects of TicketsStatusList class.
// TicketsStatusList class
class TicketsStatusList {
internal var status_id: String
internal var status_name: String
init(){
status_id = ""
status_name = ""
}
}

Resources