Converting Character and CodePoint in Swift - string

Can I convert directly between a Swift Character and its Unicode numeric value? That is:
var i:Int = ... // A plain integer index.
var myCodeUnit:UInt16 = myString.utf16[i]
// Would like to say myChar = myCodeUnit as Character, or equivalent.
or...
var j:String.Index = ... // NOT an integer!
var myChar:Character = myString[j]
// Would like to say myCodeUnit = myChar as UInt16
I can say:
myCodeUnit = String(myChar).utf16[0]
but this means creating a new String for each character. And I am doing this thousands of times (parsing text) so that is a lot of new Strings that are immediately being discarded.

The type Character represents a "Unicode grapheme cluster", which can be multiple Unicode codepoints. If you want one Unicode codepoint, you should use the type UnicodeScalar instead.

As per the swift book:
String to Code Unit
To get codeunit/ordinals for each character of the String, you can do the following:
var yourSwiftString = "甲乙丙丁"
for scalar in yourSwiftString.unicodeScalars {
print("\(scalar.value) ")
}
Code Unit to String
Because swift current does not have a way to convert ordinals/code units back to UTF, the best way I found is to still NSString. i.e. if you have int ordinals (32bit but representing the 21bit codepoints) you can use the following to convert to Unicode:
var i = 22247
var unicode_str = NSString(bytes: &i, length: 4, encoding: NSUTF32LittleEndianStringEncoding)
Obviously if you want to convert a array of ints, you'll need to pack them into a array first.

I spoke to an Apple engineer who is working on Unicode and he says they have not completed the implementation of unicode characters in strings. Are you looking at getting a code unit or a full character? Because the only and proper way to get at a full unicode character is by using a for each loop on a string. ie
for c in "hello" {
// c is a unicode character of type Character
}
But, this is not implemented as of yet.

Related

convert string to list of int in kotlin

I have a string = "1337" and I want to convert it to a list of Int, I tried to get every element in the string and convert it to Int like this string[0].toInt but I didn't get the number I get the Ascii value, I can do it with this Character.getNumericValue(number), How I do it without using a built it function? with good complexity?
What do you mean "without using a built in function"?
string[0].toInt gives you the ASCII value of the character because the fun get(index: Int) on String has a return type of Char, and a Char behaves closer to a Number than a String. "0".toInt() == 0 will yield true, but '0'.toInt() == 0 will yield false. The difference being the first one is a string and the second is a character.
A oneliner
string.split("").filterNot { it.isBlank() }.map { it.toInt() }
Explanation: split("") will take the string and give you a list of every character as a string, however, it will give you an empty string at the beginning, which is why we have filterNot { it.isBlank() }, we then can use map to transform every string in our list to Int
If you want something less functional and more imperative that doesn't make use of functions to convert there is this
val ints = mutableListOf<Int>() //make a list to store the values in
for (c: Char in "1234") { //go through all of the characters in the string
val numericValue = c - '0' //subtract the character '0' from the character we are looking at
ints.add(numericValue) //add the Int to the list
}
The reason why c - '0' works is because the ASCII values for the digits are all in numerical order starting with 0, and when we subtract one character from another, we get the difference between their ASCII values.
This will give you some funky results if you give it a string that doesn't have only digits in it, but it will not throw any exceptions.
As in Java and by converting Char to Int you get the ascii equivalence.
You can instead:
val values = "1337".map { it.toString().toInt() }
println(values[0]) // 1
println(values[1]) // 3
// ...
Maybe like this? No-digits are filtered out. The digits are then converted into integers:
val string = "1337"
val xs = string.filter{ it.isDigit() }.map{ it.digitToInt() }
Requires Kotlin 1.4.30 or higher and this option:
#OptIn(ExperimentalStdlibApi::class)

Xcode 6.1 & Swift - textField input string to integer for basic math

I am slowly understanding things in swift, I am coming for a javascript background so it is somewhat familiar.
However variables are urking me.
in JS a variable can be
var varName = 1; //Number
var varName2 = "petey" //String
var conCat = varname + varName2; // 1petey
however in swift String vars and In var are troubling me. All I want to do is capture decimal number from user input from multiple "textField" sources and store that data to variable (which i already have setup) I need to concatinate a few of them with + then do basic math with the data in the variables with * and /.
How do I make the textFeld only capture?int or how do I convert text field strings to numbers, e.g. int?
A UITextField contains a String, not an Int, so you have to convert it, e.g.
let number : Int? = textField.text.toInt()
So, there actually is a method to convert from String to Int built-in in Swift. Beware, that it returns an optional, because the conversion may fail. So you have to check for nil before you use the variable.
For your other question, take a look at e.g. UITextField - Allow only numbers and punctuation input/keypad. Basically, you will have to adapt UITextField and filter it, once there are new entries. On iOS it might be easier, because you can show a numbers-only keyboard.
The data send from the textField is String. There are multiple ways to convert an Int to a String.
var a:String="\(2+3)" //"5"
And to concatenate a String to Int :
var b:String="Hello "+"\(3*4)" //"Hello 12"
And to Convert a String to an Int from a textField:
var b:Int=textField.text.toInt()
Use the function in swift inputmethod.intValue(); if any text is entered then it returns with a 0.

Specman string: How to split a string to a list of its chars?

I need to split a uint to a list of bits (list of chars, where every char is "0" or "1", is also Ok). The way I try to do it is to concatenate the uint into string first, using binary representation for numeric types - bin(), and then to split it using str_split_all():
var num : uint(bits:4) = 0xF; // Can be any number
print str_split_all(bin(num), "/w");
("/w" is string match pattern that means any char).
The output I expect:
"0"
"b"
"1"
"1"
"1"
"1"
But the actual output is:
0. "0b1111"
Why doesn't it work? Thank you for your help.
If you want to split an integer into a list of bits, you can use the %{...} operator:
var num_bits : list of bit = %{num};
You can find a working example on EDAPlayground.
As an extra clarification to your question, "/w" doesn't mean match any character. The string "/\w/" means match any single character in AWK Syntax. If you put that into your match expression, you'll get (almost) the output you want, but with some extra blanks interleaved (the separators).
Regardless, if you want to split a string into its constituting characters, str_split_all(...) isn't the way to go. It's easier to convert the string into ASCII characters and then convert those back to string again:
extend sys {
run() is also {
var num : uint(bits:4) = 0xF; // Can be any number
var num_bin : string = bin(num);
var num_bin_chars := num_bin.as_a(list of byte);
for each (char) in num_bin_chars {
var char_as_string : string;
unpack(packing.low, %{8'b0, char}, char_as_string);
print char_as_string;
};
};
};
The unpack(...) syntax is directly from the e Reference Manual, Section 2.8.3 Type Conversion Between Strings and Scalars or Lists of Scalars

Raw Strings in Swift

Is there a functional equivalent in Swift to Scala's Raw String or the verbatim string literal in C#?
Sample raw string without escape characters (not syntactically correct):
val secretKey = """long\^578arandom&61~8791escaped&*^%#(chars"""
I've tried briefly gripping through the language docs but haven't found a functional equivalent yet.
Swift 5 supports raw strings now. With this feature, backslashes and quote marks are interpreted as to their respective literal symbols. They are not treated as escapes characters or string terminators in raw strings.
To use raw strings, # symbol is used(same as python uses ‘r’ or ‘R’). Here are the number of variations for using raw strings in swift 5:
let myPets = #"The name of my dog is "barky" and my cat is "smily"."#
//The name of my dog is "barky" and my cat is "smily".
Inside of the raw string # is used for string interpolation instead of usual backslash of swift.
let val = 1
let result = #"The answer is \#(val)."#
//The answer is 1
If you want to use # inside of a raw string, place ## at the beginning and at the end.
let str = ##"I am happy bla#blablabla"##
//"I am happy bla#blablabla"
Raw strings will be helpful for regular expressions I guess, lesser backslashes in regex definition. For example:
let regex_Prev = "\\\\[A-Z]+[A-Za-z]+\\.[a-z]+"
Now we can write:
let regex_Swift5version = #"\\[A-Z]+[A-Za-z]+\.[a-z]+"#
Supposedly, this is implemented in Swift 5, see SE-0200 – Support Raw Text. From the document:
You may pad a string literal with one or more # characters:
#"She said, "This is dialog!""#
// Equivalent to "She said, \"This is dialog!\""
#"A \"quote"."#
// Backslash interpreted as an extra character.
Currently expected Swift 5 release date: “Early 2019”.
There is currently no such function, swift is new. In the conference speakers encouraged us to report anything that you feel swift needs. Therefore I suggest you to report that you need a raw string function like Scala.

How to get the ASCII value of a string

Suppose there is a string:
String str="Hello";
HOw can i get the ASCII value of that above mentioned string?
Given your comment, it sounds like all you need is:
char[] chars = str.ToCharArray();
Array.Sort(chars);
A char value in .NET is actually a UTF-16 code unit, but for all ASCII characters, the UTF-16 code unit value is the same as the ASCII value anyway.
You can create a new string from the array like this:
string sortedText = new string(chars);
Console.WriteLine(chars);
As it happens, "Hello" is already in ascending ASCII order...
byte[] asciiBytes =Encoding.ASCII.GetBytes(str);
You now have an array of the ASCII value of the bytes

Resources