I need to use replacingOccurrences to get a new string, but my question is, I can't use let in if.
I don't know how to do...confused so much till now
my issue just like what I quote in title, it is system warning.and my code as below:
let newlastfive1 = lastfive
let newlastfive2 = lastfive
let newlastfive3 = lastfive
//replace aeoiu
if (lastfive.range(of: "a", options: .regularExpression) != nil)
{
let newlastfive1 = lastfive.replacingOccurrences(of: "a", with: "á")
let newlastfive2 = lastfive.replacingOccurrences(of: "a", with: "ǎ")
let newlastfive3 = lastfive.replacingOccurrences(of: "a", with: "à")
}
if (lastfive.range(of: "e", options: .regularExpression) != nil)
{
newlastfive1.replacingOccurrences(of: "e", with: "é")
newlastfive2.replacingOccurrences(of: "e", with: "ě")
newlastfive3.replacingOccurrences(of: "e", with: "è")
}
if (lastfive.range(of: "o", options: .regularExpression) != nil)
{
newlastfive1.replacingOccurrences(of: "o", with: "ó")
newlastfive2.replacingOccurrences(of: "o", with: "ǒ")
newlastfive3.replacingOccurrences(of: "o", with: "ò")
}
if (lastfive.range(of: "i", options: .regularExpression) != nil)
{
newlastfive1.replacingOccurrences(of: "i", with: "í")
newlastfive2.replacingOccurrences(of: "i", with: "ǐ")
newlastfive3.replacingOccurrences(of: "i", with: "ì")
for I need to replace only one character in "aeiou",
this mean when we have two, we need to decide which one we need to pick.
for example, this string "hallo", in this case, we need to pick "a",not "a"&"o", only one character once.
priority should follow this : a>e>o>I>u>ü
I'm going to guess that you want 3 copies of the original string, each with letter-to-letter replacements?
Take a look at this code:
let origString: String = "This is your test of looping replacement"
// characters to replace
let origChars: [String] = ["a", "e", "i", "o", "u"]
// replace with these characters
let replChars: [[String]] = [
["á", "é", "í", "ó", "ú"],
["ǎ", "ě", "ǐ", "ǒ", "ǔ"],
["à", "è", "ì", "ò", "ù"],
]
// mutable array of copies of the original string
var resultStrings: [String] = Array(repeating: origString, count: replChars.count)
// for each copy
for i in 0..<resultStrings.count {
// for each orig char
for (oChar, rChar) in zip(origChars, replChars[i]) {
// replace with replacement car
resultStrings[i] = resultStrings[i].replacingOccurrences(of: oChar, with: rChar)
}
}
// print the original string
print(origString)
// print the resulting replacement strings
resultStrings.forEach {
print($0)
}
The output in the debug console is:
This is your test of looping replacement
Thís ís yóúr tést óf lóópíng réplácémént
Thǐs ǐs yǒǔr těst ǒf lǒǒpǐng rěplǎcěměnt
Thìs ìs yòùr tèst òf lòòpìng rèplàcèmènt
If you have more "replacement sets" you can add them to the replChars array:
// replace with these characters
let replChars: [[String]] = [
["á", "é", "í", "ó", "ú"],
["ǎ", "ě", "ǐ", "ǒ", "ǔ"],
["à", "è", "ì", "ò", "ù"],
// add more sets
["1", "2", "3", "4", "5"],
["ⓐ", "ⓔ", "ⓘ", "ⓞ", "ⓤ"],
]
Now the output in the debug console is:
This is your test of looping replacement
Thís ís yóúr tést óf lóópíng réplácémént
Thǐs ǐs yǒǔr těst ǒf lǒǒpǐng rěplǎcěměnt
Thìs ìs yòùr tèst òf lòòpìng rèplàcèmènt
Th3s 3s y45r t2st 4f l44p3ng r2pl1c2m2nt
Thⓘs ⓘs yⓞⓤr tⓔst ⓞf lⓞⓞpⓘng rⓔplⓐcⓔmⓔnt
Related
The output of the [Character] Array currently is:
["E", "x", "a", "m", "p", "l", "e"]
It should be:
Example
It could be that " is in the array, like this: """. That output should be ".
Thank you!
The other answer(s) cover the case where your array is one of String elements (which is most likely the case here: since you haven't supplied us the type of the array, we could use Swift own type inference rules to speculatively infer the type to be [String]).
In case the elements of your array are in fact of type Character, however, you could use the Character sequence initializer of String directly:
let charArr: [Character] = ["E", "x", "a", "m", "p", "l", "e"]
let str = String(charArr) // Example
W.r.t. your comment below: if your example array is, for some reason, one of Any elements (which is generally not a good idea to use explicitly, but sometimes the case when recieving data from some external source), you first need to perform an attempted conversion of each Any element to String type, prior to concenating the converted elements to a single String instance. After the conversion, you will be working with an array of String elements, in which case the methods shown in the other answers will be the appropriate method of concenation:
// e.g. using joined()
let arr: [Any] = ["E", "x", "a", "m", "p", "l", "e"]
let str = arr.flatMap { $0 as? String }.joined()
print(str) // example
You could naturally also (attempt to) convert from Any to Character elements, but even in this case you would have to go via String instances, which means that for the [Any] case, the joined() alternative above is to prefer over the one below:
let arr: [Any] = ["E", "x", "a", "m", "p", "l", "e"]
let str = String(arr.flatMap { ($0 as? String)?.characters.first })
print(str) // example
Just use joined() with default "" separator:
let joinedString = ["E", "x", "a", "m", "p", "l", "e"].joined()
let e = ["E", "x", "a", "m", "p", "l", "e"]
print(e.reduce ("", +))
Is there a way to generate a set from an Integer? It would convenient if we have a number_of_instances parameter that is converted to set to be used in for_each Meta-Argument. In result, we don't need to write:
for_each = toset(["one", "two", "three",])
In stead, we just set a parameter:
number_of_instances = 3
For now I came up with this:
variable "number_of_instances" {
type = number
default = 0
}
locals {
i = [
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
]
}
resource "null_resource" "main" {
for_each = toset(slice(local.i, 0, var.number_of_instances))
connection {
name = each.key
}
}
May you could the following:
variable "number_of_instances" {
default = 3
}
locals {
numbers = ["one", "two", "three", "four", "five", "six"]
number_set = slice(local.numbers, 0, var.number_of_instances)
}
and then use:
for_each = toset(local.number_set)
Off course numbers must be pre-populated first.
i have to filter dictionary containing my text inside of textfield
//my code
var arrayData = [["Name":"Sahil"],["Name":"Raman"],["Name":"ashish"],["Name":"Vishnu"],["Name":"Deep"],["Name":"sahil"],["Name":"Swift"]]
//my result should be like this
[["Name":"Sahil"],["Name":"ashish"],["Name":"Vishnu"],["Name":"Swift"]]
It was unclear, you explained it later in comments, but you want to keep the values for key "Name" which contains an "s" case insensitive.
Let's add a couple of additional values to show why your previous attempts failed:
var arrayData = [["Name":"Sahil"],
["Name":"Raman"],
["Name":"ashish"],
["Name":"Vishnu"],
["Name":"Deep"],
["Name":"sahil"],
["Name":"Swift"],
["Name":"s"],
["Name":"S"]]
And simplify:
let searchText = "s" // textField.text ?? ""
You attempted:
let filteredArray1 = arrayData.filter { $0["Name"] == searchText }
print(filteredArray1)
Output:
$> [["Name": "s"]]
So, you get only when value is exactly equals to "s", that's normal, you are using ==
You then attempted:
let filteredArray2 = arrayData.filter { $0["Name"]!.contains(searchText) }
print(filteredArray2)
Output:
$>[["Name": "ashish"], ["Name": "Vishnu"], ["Name": "sahil"], ["Name": "s"]]
So, you are getting anyvalues when it has a "s" inside it. It's almost that, but you aren't getting when it has an uppercase "S".
To do that, you can use range(of:options:searchRange:local:) with .caseInsensitive optiono. If the result isn't nil, it means it has been found.
So you can use:
let filteredArray3 = arrayData.filter { $0["Name"]?.range(of: "s", options: .caseInsensitive) != nil }
print(filteredArray3)
Output:
$>[["Name": "Sahil"], ["Name": "ashish"], ["Name": "Vishnu"], ["Name": "sahil"], ["Name": "Swift"], ["Name": "s"], ["Name": "S"]]
This should work:
var arrayDataFiltered = arrayData.filter { $0["Name"]?.lowercased().contains("s") ?? false }
Here is the documentation for filtering:
https://developer.apple.com/documentation/swift/sequence/3018365-filter
When I use flatMap with String type array it didn't give any warning, while it gives warning in case of Int type array. Why? Example:
let strings = [
"I'm excited about #SwiftUI",
"#Combine looks cool too",
"This year's #WWDC was amazing"
]
strings.flatMap{$0 + "."} //No warning
let ints = [
2,3,4
]
ints.flatMap{$0 + 1} //'flatMap' is deprecated: Please use compactMap(_:) for the case where closure returns an optional value
It is because these are two different flatMap methods.
So, before I answer your question, let’s step back and consider what flatMap is now intended to do, namely, applying transform to a sequence and concatenating the resulting sequences. The typical example is used for “flattening” arrays of arrays):
let arrayOfArrays = [[1, 2], [3, 4, 5]]
let array = arrayOfArrays.flatMap { $0 }
print(array)
Resulting in:
[1, 2, 3, 4, 5]
The flatMap has flattened the array of arrays to a single array.
Confusingly, there was another, now deprecated, flatMap that would perform the transform, unwrapping optional results in a sequence or collection, but removing those that were nil. Fortunately, that has now been renamed to compactMap to avoid confusion. So, this is why you got your warning.
Consider:
let input: [Int?] = [0, 1, nil, 3]
let results = input.flatMap { $0 } // 'flatMap' is deprecated: Please use compactMap(_:) for the case where closure returns an optional value
print(results)
Resulting in:
[0, 1, 3]
So, we should replace flatMap with compactMap, as advised:
let input: [Int?] = [0, 1, nil, 3]
let results = input.compactMap { $0 }
print(results)
That will give us the desired results, without the warning.
So, let’s go back to your examples. Because strings are arrays of characters, it will take you at your word and flatten that down:
let strings = [
"I'm excited about #SwiftUI",
"#Combine looks cool too",
"This year's #WWDC was amazing"
]
let stringResults = strings.flatMap { $0 + "." }
print(stringResults)
The result of that is a flattened array of characters:
["I", "\'", "m", " ", "e", "x", "c", "i", "t", "e", "d", " ", "a", "b", "o", "u", "t", " ", "#", "S", "w", "i", "f", "t", "U", "I", ".", "#", "C", "o", "m", "b", "i", "n", "e", " ", "l", "o", "o", "k", "s", " ", "c", "o", "o", "l", " ", "t", "o", "o", ".", "T", "h", "i", "s", " ", "y", "e", "a", "r", "\'", "s", " ", "#", "W", "W", "D", "C", " ", "w", "a", "s", " ", "a", "m", "a", "z", "i", "n", "g", "."]
That obviously not what you intended, but the compiler took you at your word that you wanted to flatten the array of array of characters (i.e. the array of strings) into a flat array of characters. So that’s why there was no warning.
Needless to say, in your examples, you would use neither flatMap (because you aren’t dealing with arrays of arrays) nor compactMap (because you aren’t dealing with optionals). You’d just use map:
let strings = [
"I'm excited about #SwiftUI",
"#Combine looks cool too",
"This year's #WWDC was amazing"
]
let stringsResults = strings.map { $0 + "." }
print(stringsResults)
let ints = [2, 3, 4]
let intsResults = ints.map { $0 + 1 }
print(intsResults)
Completely unrelated, but in the interest of full disclosure (but at the risk of making it even more confusing), there is actually yet another flatMap method (!), one on the Optional type. Admittedly, this is arguable used less commonly than the array flattening (i.e. sequence concatenating) rendition, but I should probably acknowledge its existence.
This flatMap method on Optional “Evaluates the given closure when this Optional instance is not nil, passing the unwrapped value as a parameter.” But if the optional was nil, this flatMap will return nil, too.
For example:
func message(for value: Int?) -> String? {
return value.flatMap { "The value is \($0)" }
}
Thus, if value was 42, result would be the optional string, "The value is 42". But if value was nil, then result will be nil.
This rendition of flatMap is not relevant to the question at hand, but I wanted to mention it for the sake of completeness.
How can I convert a String "Hello" to an Array ["H","e","l","l","o"] in Swift?
In Objective-C I have used this:
NSMutableArray *characters = [[NSMutableArray alloc] initWithCapacity:[myString length]];
for (int i=0; i < [myString length]; i++) {
NSString *ichar = [NSString stringWithFormat:#"%c", [myString characterAtIndex:i]];
[characters addObject:ichar];
}
It is even easier in Swift:
let string : String = "Hello 🐶🐮 🇩🇪"
let characters = Array(string)
println(characters)
// [H, e, l, l, o, , 🐶, 🐮, , 🇩🇪]
This uses the facts that
an Array can be created from a SequenceType, and
String conforms to the SequenceType protocol, and its sequence generator
enumerates the characters.
And since Swift strings have full support for Unicode, this works even with characters
outside of the "Basic Multilingual Plane" (such as 🐶) and with extended grapheme
clusters (such as 🇩🇪, which is actually composed of two Unicode scalars).
Update: As of Swift 2, String does no longer conform to
SequenceType, but the characters property provides a sequence of the
Unicode characters:
let string = "Hello 🐶🐮 🇩🇪"
let characters = Array(string.characters)
print(characters)
This works in Swift 3 as well.
Update: As of Swift 4, String is (again) a collection of its
Characters:
let string = "Hello 🐶🐮 🇩🇪"
let characters = Array(string)
print(characters)
// ["H", "e", "l", "l", "o", " ", "🐶", "🐮", " ", "🇩🇪"]
Edit (Swift 4)
In Swift 4, you don't have to use characters to use map(). Just do map() on String.
let letters = "ABC".map { String($0) }
print(letters) // ["A", "B", "C"]
print(type(of: letters)) // Array<String>
Or if you'd prefer shorter: "ABC".map(String.init) (2-bytes 😀)
Edit (Swift 2 & Swift 3)
In Swift 2 and Swift 3, You can use map() function to characters property.
let letters = "ABC".characters.map { String($0) }
print(letters) // ["A", "B", "C"]
Original (Swift 1.x)
Accepted answer doesn't seem to be the best, because sequence-converted String is not a String sequence, but Character:
$ swift
Welcome to Swift! Type :help for assistance.
1> Array("ABC")
$R0: [Character] = 3 values {
[0] = "A"
[1] = "B"
[2] = "C"
}
This below works for me:
let str = "ABC"
let arr = map(str) { s -> String in String(s) }
Reference for a global function map() is here: http://swifter.natecook.com/func/map/
There is also this useful function on String: components(separatedBy: String)
let string = "1;2;3"
let array = string.components(separatedBy: ";")
print(array) // returns ["1", "2", "3"]
Works well to deal with strings separated by a character like ";" or even "\n"
For Swift version 5.3 its easy as:
let string = "Hello world"
let characters = Array(string)
print(characters)
// ["H", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]
Updated for Swift 4
Here are 3 ways.
//array of Characters
let charArr1 = [Character](myString)
//array of String.element
let charArr2 = Array(myString)
for char in myString {
//char is of type Character
}
In some cases, what people really want is a way to convert a string into an array of little strings with 1 character length each. Here is a super efficient way to do that:
//array of String
var strArr = myString.map { String($0)}
Swift 3
Here are 3 ways.
let charArr1 = [Character](myString.characters)
let charArr2 = Array(myString.characters)
for char in myString.characters {
//char is of type Character
}
In some cases, what people really want is a way to convert a string into an array of little strings with 1 character length each. Here is a super efficient way to do that:
var strArr = myString.characters.map { String($0)}
Or you can add an extension to String.
extension String {
func letterize() -> [Character] {
return Array(self.characters)
}
}
Then you can call it like this:
let charArr = "Cat".letterize()
An easy way to do this is to map the variable and return each Character as a String:
let someText = "hello"
let array = someText.map({ String($0) }) // [String]
The output should be ["h", "e", "l", "l", "o"].
for the function on String: components(separatedBy: String)
in Swift 5.1
have change to:
string.split(separator: "/")
Martin R answer is the best approach, and as he said, because String conforms the SquenceType protocol, you can also enumerate a string, getting each character on each iteration.
let characters = "Hello"
var charactersArray: [Character] = []
for (index, character) in enumerate(characters) {
//do something with the character at index
charactersArray.append(character)
}
println(charactersArray)
let string = "hell0"
let ar = Array(string.characters)
print(ar)
In Swift 4, as String is a collection of Character, you need to use map
let array1 = Array("hello") // Array<Character>
let array2 = Array("hello").map({ "\($0)" }) // Array<String>
let array3 = "hello".map(String.init) // Array<String>
You can also create an extension:
var strArray = "Hello, playground".Letterize()
extension String {
func Letterize() -> [String] {
return map(self) { String($0) }
}
}
func letterize() -> [Character] {
return Array(self.characters)
}
Suppose you have four text fields otpOneTxt, otpTwoTxt, otpThreeTxt, otpFourTxt and a string getOtp.
let getup = "5642"
let array = self.getOtp.map({ String($0) })
otpOneTxt.text = array[0] //5
otpTwoTxt.text = array[1] //6
otpThreeTxt.text = array[2] //4
otpFourTxt.text = array[3] //2
let str = "cdcd"
let characterArr = str.reduce(into: [Character]()) { result, letter in
result.append(letter)
}
print(characterArr)
//["c", "d", "c", "d"]