I have a number, I want to insert a column ":" between each two consecutive digits inside that number, and get a String as a result
For example:
let number: Int = 34567
let result: String = "3:4:5:6:7"
Thanks for any help,
Possible solution:
let result = String(number).map({ String($0) }).joined(separator: ":")
With explanation of intermediary results to help understand what's going on on theses 3 chained methods:
let interemdiary1 = String(number)
print("interemdiary1: \(interemdiary1)")
let interemdiary2 = interemdiary1.map({ String($0 )})
print("interemdiary2: \(interemdiary2)")
let interemdiary3 = interemdiary2.joined(separator: ":")
print("interemdiary3: \(interemdiary3)")
Output:
$>interemdiary1: 34567
$>interemdiary2: ["3", "4", "5", "6", "7"]
$>interemdiary3: 3:4:5:6:7
First, let's transform your number into a String.
Then, let's create an array of it where each character (as a String) of the previous result is an element of it. I used a map() of it.
Finally, we use joined(separator:) to assemble them.
Another kind of solution can be found there:
How add separator to string at every N characters in swift? It's just that you do it each 1 characters.
You need to join it by :
use this
let result = String(number).map({String($0)}).joined(separator: ":")
Related
Suppose you get an input like below:
hello
helloSwift
Swi
Apple
le
(total 5)
I want a function to receive the above inputs and return a String "helloSwiftApple".
The returning String must "include" all input Strings without repetitions. For instance, the returning String can't be "hellohelloSwiftSwiApplele" How can I do this with Swift?
Thanks in advance and sorry for my bad explanation. Just got started studying algorithm using Swift.
This is a bit of a "brute force" approach, but it may work for you.
split the string into an array a of unique "words"
loop through the array for i in 0..<a.count
remove element i word
does any element in a contain word?
if NO
add word to new array
put word back in a
return newArray joined into string
So, we can use this extension to remove duplicates from an array (Hacking with Swift):
extension Array where Element: Hashable {
func removingDuplicates() -> [Element] {
var addedDict = [Element: Bool]()
return filter {
addedDict.updateValue(true, forKey: $0) == nil
}
}
mutating func removeDuplicates() {
self = self.removingDuplicates()
}
}
and we can write a func like this:
func parseString(_ str: String) -> String {
// split the string into an array of "words" (no spaces)
var a1: [String] = str.components(separatedBy: " ").removingDuplicates()
// an array to hold the unique words
var a2: [String] = []
// for each word
for i in 0..<a1.count {
// remove the word from the array
let word = a1.remove(at: i)
// filter the remaining array by elements containing word
let n = a1.filter { $0.contains(word) }
// if no elements contain word
if n.count == 0 {
// append it to array of unique words
a2.append(word)
}
// put the word back into the full array
a1.insert(word, at: i)
}
// change "-" to "" for no separators
return a2.joined(separator: "-")
}
A quick test like this:
let test: [String] = [
"1 hello helloSwift Swi Apple le",
"2 I want a string",
"3 i want a string",
"4 I want a function to receive the above inputs and return a String",
"5 i want a function to receive the above inputs and return a String",
"6 abc aBc Abc abc ABC aabc",
"7 droid android otherdroid and android and otherdroid",
]
test.forEach { s in
let rs = parseString(s)
print("Orig:", s)
print("Ret :", rs)
print()
}
outputs this to the debug console:
Orig: 1 hello helloSwift Swi Apple le
Ret : 1-helloSwift-Apple
Orig: 2 I want a string
Ret : 2-I-want-string
Orig: 3 i want a string
Ret : 3-want-string
Orig: 4 I want a function to receive the above inputs and return a String
Ret : 4-I-want-function-to-receive-the-above-inputs-and-return-String
Orig: 5 i want a function to receive the above inputs and return a String
Ret : 5-want-function-to-receive-the-above-inputs-and-return-String
Orig: 6 abc aBc Abc abc ABC aabc
Ret : 6-aBc-Abc-ABC-aabc
Orig: 7 droid android otherdroid and android and otherdroid
Ret : 7-android-otherdroid
As you'll immediately notice, you didn't mention case-sensitivity, so we haven't addressed that... that's why examples 2 & 3 and 4 & 5 return different results:
"I" is not found in "string"
"i" is found in "string"
I would like to take an array of [String] and split it up into a given number of groups.
I have tried using this extension
extension Array {
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to:count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)])
}
}
}
to split the array into a given number of elements per subarray, which for that function it works.
But to split it into a desired number of subarrays, I tried dividing the array.count by the desired number of teams, which works but only in certain circumstances.
If there are any extra elements, it puts them into an extra subarray at the end, and the number needs to come out even if I want this to work perfectly, which is the minority of the time.
So I guess this array.chunked function is not the solution in any way.
Maybe there is a way to do it with a for loop by taking an array.randomElement(), adding that to a variable (which would be a team) and then removing that element from the original array, and iterating over it until the original array is empty. And end up with an array of subarrays which would be the teams, or just separate variables which would be the teams. It could be any of those options.
Any ideas on how to do this?
Think about how you deal cards.
If you have 7 players, you start with one player and go around, giving one card at a time to each player. At the end, you may run out of cards before giving everybody the same number of cards. Some people may have n cards, and some may have n-1. That's the best that you can do.
You could implement the same thing with a source array and your destination arrays. Remove one element at a time from the source array, and "round-robbin" add it to one of the destination arrays until the source array is exhausted.
That code might look like this:
func splitArray<T>(array: [T], subArrayCount: Int) -> [[T]] {
// Create an empty array of arrays
var result = [[T]]()
// Create the empty inner string arrays
for _ in 1...subArrayCount {
let innerArray = [T]()
result.append(innerArray)
}
for (index, element) in array.enumerated() {
result[index % subArrayCount].append(element)
}
return result
}
And to test it:
let string = "Now is the time for all good programmers to babble incoherently. The rain in spain falls mainly on the plain. Fourscore and seven years ago our forefathers brought forth to this continent a new nation conceived in liberty and dedicated to the cause that all men are created equal."
let array = string.split(separator: " ")
.map { String($0) }
let subArrays: [[String]] = splitArray(array: array, subArrayCount: 5)
for (index, array) in subArrays.enumerated() {
let countString = String(format: "%2d", array.count)
print ("Array[\(index)]. Count = \(countString). Contents = \(array)")
}
The output of that test is:
Array[0]. Count = 10. Contents = ["Now", "all", "incoherently.", "falls", "Fourscore", "our", "this", "conceived", "to", "men"]
Array[1]. Count = 10. Contents = ["is", "good", "The", "mainly", "and", "forefathers", "continent", "in", "the", "are"]
Array[2]. Count = 10. Contents = ["the", "programmers", "rain", "on", "seven", "brought", "a", "liberty", "cause", "created"]
Array[3]. Count = 10. Contents = ["time", "to", "in", "the", "years", "forth", "new", "and", "that", "equal."]
Array[4]. Count = 9. Contents = ["for", "babble", "spain", "plain.", "ago", "to", "nation", "dedicated", "all"]
I have strings like
"\U0aac\U0ab9\U0ac1\U0ab5\U0a9a\U0aa8",
"\U0a97\U0ac1\U0ab8\U0acd\U0ab8\U0acb",
"\U0aa6\U0abe\U0ab5\U0acb",
"\U0a96\U0a82\U0aa1"
But I want to split this strings by unicode character
I dont know hot to do. I know components seprated by function but it's no use here.
\nAny help would be apperiaciated
If the strings you're getting really contain \U characters, you need to parse them manually and extract the unicode scalar values. Something like this:
let strings = [
"\\U0aac\\U0ab9\\U0ac1\\U0ab5\\U0a9a\\U0aa8",
"\\U0a97\\U0ac1\\U0ab8\\U0acd\\U0ab8\\U0acb",
"\\U0aa6\\U0abe\\U0ab5\\U0acb",
"\\U0a96\\U0a82\\U0aa1"
]
for str in strings {
let chars = str.components(separatedBy: "\\U")
var string = ""
for ch in chars {
if let val = Int(ch, radix: 16), let uni = Unicode.Scalar(val) {
string.unicodeScalars.append(uni)
}
}
print(string)
}
You can map your array, split its elements at non hexa digit values, compact map them into UInt32 values, initializate unicode scalars with them and map the resulting elements of your array into a UnicodeScalarView and init a new string with it:
let arr = [
#"\U0aac\U0ab9\U0ac1\U0ab5\U0a9a\U0aa8"#,
#"\U0a97\U0ac1\U0ab8\U0acd\U0ab8\U0acb"#,
#"\U0aa6\U0abe\U0ab5\U0acb"#,
#"\U0a96\U0a82\U0aa1"#]
let strings = arr.map {
$0.split { !$0.isHexDigit }
.compactMap { UInt32($0, radix: 16) }
.compactMap(Unicode.Scalar.init)
}.map { String(String.UnicodeScalarView($0)) }
print(strings)
This will print
["બહુવચન", "ગુસ્સો", "દાવો", "ખંડ"]
So, the string that comes back already has the "\" because in order to use components you'd need to have an additional escaping "\" so that you'd be able to do:
var listofCodes = ["\\U0aac\\U0ab9\\U0ac1\\U0ab5\\U0a9a\\U0aa8", "\\U0aac\\U0ab9\\U0ac1\\U0ab5\\U0a9a\\U0aa8"]
var unicodeArray :[String] = []
listofCodes.forEach { string in
unicodeArray
.append(contentsOf: string.components(separatedBy: "\\"))
unicodeArray.removeAll(where: {value in value == ""})
}
print(unicodeArray)
I will revise this answer once you specify how you are obtaining these strings, as is I get a non-valid string error from the start.
Sorry,I'm new of swift. I want to calculate the target char in string.But I don't know how to do.Have any good suggestion to me?Thanks.
let string = "hello\nNice to meet you.\nMy name is Leo.\n" //I want to get 3
If you simply want a count of newline characters then you can use a filter on the string's characters:
let string = "hello\nNice to meet you.\nMy name is Leo.\n"
let count = string.characters.filter { $0 == "\n" }.count
print(count)
This outputs 3 as expected.
An alternative is to split the lines with the components(separatedBy method:
let string = "hello\nNice to meet you.\nMy name is Leo.\n"
let lineCounter = string.components(separatedBy: "\n").count - 1
or more versatile to consider all kinds of newline characters
let lineCounter = string.components(separatedBy: CharacterSet.newlines).count - 1
Due to the trailing newline character the result is 4. To ignore a trailing new line you have to decrement the result.
I'm wondering how I can split a string containing several sentences into an array of the sentences.
I know about the split function but spliting by "." doesn't suite for all cases.
Is there something like mentioned in this answer
You can use NSLinguisticsTagger to identify SentenceTerminator tokens and then split into an array of strings from there.
I used this code and it worked great.
https://stackoverflow.com/a/57985302/10736184
let text = "My paragraph with weird punctuation like Nov. 17th."
var r = [Range<String.Index>]()
let t = text.linguisticTags(
in: text.startIndex..<text.endIndex,
scheme: NSLinguisticTagScheme.lexicalClass.rawValue,
tokenRanges: &r)
var result = [String]()
let ixs = t.enumerated().filter {
$0.1 == "SentenceTerminator"
}.map {r[$0.0].lowerBound}
var prev = text.startIndex
for ix in ixs {
let r = prev...ix
result.append(
text[r].trimmingCharacters(
in: NSCharacterSet.whitespaces))
prev = text.index(after: ix)
}
Where result will now be an array of sentence strings. Note that the sentence will have to be terminated with '?', '!', '.', etc to count. If you want to split on newlines as well, or other Lexical Classes, you can add
|| $0.1 == "ParagraphBreak"
after
$0.1 == "SentenceTerminator"
to do that.
If you are capable of using Apple's Foundation then solution could be quite straightforward.
import Foundation
var text = """
Let's split some text into sentences.
The text might include dates like Jan.13, 2020, words like S.A.E and numbers like 2.2 or $9,999.99 as well as emojis like 👨👩👧👦! How do I split this?
"""
var sentences: [String] = []
text.enumerateSubstrings(in: text.startIndex..., options: [.localized, .bySentences]) { (tag, _, _, _) in
sentences.append(tag ?? "")
}
There are ways do it with pure Swift of course. Here is quick and dirty split:
let simpleText = """
This is a very simple text.
It doesn't include dates, abbreviations, and numbers, but it includes emojis like 👨👩👧👦! How do I split this?
"""
let sentencesPureSwift = simpleText.split(omittingEmptySubsequences:true) { $0.isPunctuation && !Set("',").contains($0)}
It could be refined with reduce().
Take a look on this link :
How to create String split extension with regex in Swift?
it shows how to combine regex and componentsSeparatedByString.
Try this:-
var myString : NSString = “This is a test”
var myWords: NSArray = myString.componentsSeparatedByString(“ “)
//myWords is now: ["This", "is", "a", "test"]