I'm trying to use inertContentsOf to loop through and find all "\" characters and insert another "\" character in front of it. The problem is I won't always know the index if the character I need to insert.
For example, I know I want to insert "\" at index 3:
myString.insertContentsOf("\\".characters, at: myString.startIndex.advancedBy(3))
How would I do this without knowing the index?
I've tried the following for loops but haven't had any luck.
for words in inputArray {
for char in words {
if char == "\\" {
words.insertContentsOf("\\".characters, at: char)
}
}
}
at: char yells at me for trying to convert a character to an index, which I get but don't know how to fix it.
Edit: For some reason when I try and put it in a function inputArray.map doesn't get called.
func GenerateString(inputArray:[String])->String {
inputArray.map {
$0.stringByReplacingOccurrencesOfString("\\", withString: "\\\\")
}
let joiner = "|"
let joinerString = inputArray.joinWithSeparator(joiner)
return ("Result: \(joinerString)")
}
let example = ["hello", "world", "c:\Program File\Example"]
GenerateString(example)
Result:
"Hello|world|c:\Program File\Example"
Use stringByReplacingOccurrencesOfString instead:
words.stringByReplacingOccurrencesOfString("\\", withString: "\\\\")
Try stringByReplacingOccurrencesOfString:
var words: String = "c\\Program Files\\Example"
words = words.stringByReplacingOccurrencesOfString("\\", withString: "\\\\")
print("Result: \(words)")
// "Result: c\\Program Files\\Example"
or if you want to do this in a array:
let inputArray: [String] = ["hello", "world", "c\\Program Files\\Example"]
inputArray.map {
$0.stringByReplacingOccurrencesOfString("\\", withString: "\\\\")
}
print("Result: \(inputArray)")
// "Result: ["hello", "world", "c\\Program Files\\Example"]"
stringByReplacingOccurrencesOfString("\\", withString: "\\\\") line means replace \\ with \\\\ and it's exactly what you want to do. :)
Related Questions: Any way to replace characters on Swift String?
You can call enumerate() on any sequence that is a SequenceType to get the index along with the current item so you can do something like:
for (index, char) in words.enumerate()
Although you should also avoid modifying an array while looping it. Think maybe about having another array where you add normal characters to it, and in the case of \, you add \\
You can do map on your array and use stringByReplacingOccurrencesOfString
let new Array = inputArray.map {
$0.stringByReplacingOccurrencesOfString("\\", withString: "\\\\")
}
Related
I want to convert c-style define names to camelcase.
Example: BLA_BLA -> blaBla
I created the following function:
private str camelCaseName(n) {
rVal = n;
if (contains(rVal, "_")) {
rVal = toLowerCase(rVal);
for (pos <- findAll(rVal, "_")) {
up = toUpperCase(stringChar(charAt(rVal, pos + 1)));
charList = chars(rVal);
charList = delete(charList, pos + 1);
charList = insertAt(charList, pos + 1, charAt(up, 0));
rVal = stringChars(charList);
}
// rVal = replaceAll(rVal, "_", "");
}
return rVal;
}
This works well for changing the case. However if I uncomment the replaceAll then a call that uses the string reports "Expected str, but got tuple[value,value,value]".
I guess there is an easier way to get this functionality.
I'm not sure what goes wrong with the replaceAll function, but I'd try the static checker on this code and read its error message.
Another way of writing the function:
private str camelCaseName(str n) {
words = split("_", toLowerCase(n));
return "<words[0]><for (w <- words[1..]) {><capitalize(w)><}>";
}
I added a type to the parameter n, that's obligatory.
String templates are a nice way of printing out stuff in a string.
The split function is handy; it splits a string into list elements.
The capitalize function changes the first letter of a word to a capital
many examples in SO are fixing both sides, the leading and trailing. My request is only about the trailing.
My input text is: " keep my left side "
Desired output: " keep my left side"
Of course this command will remove both ends:
let cleansed = messageText.trimmingCharacters(in: .whitespacesAndNewlines)
Which won't work for me.
How can I do it?
A quite simple solution is regular expression, the pattern is one or more(+) whitespace characters(\s) at the end of the string($)
let string = " keep my left side "
let cleansed = string.replacingOccurrences(of: "\\s+$",
with: "",
options: .regularExpression)
You can use the rangeOfCharacter function on string with a characterSet. This extension then uses recursion of there are multiple spaces to trim. This will be efficient if you only usually have a small number of spaces.
extension String {
func trailingTrim(_ characterSet : CharacterSet) -> String {
if let range = rangeOfCharacter(from: characterSet, options: [.anchored, .backwards]) {
return self.substring(to: range.lowerBound).trailingTrim(characterSet)
}
return self
}
}
"1234 ".trailingTrim(.whitespaces)
returns
"1234"
Building on vadian's answer I found for Swift 3 at the time of writing that I had to include a range parameter. So:
func trailingTrim(with string : String) -> String {
let start = string.startIndex
let end = string.endIndex
let range: Range<String.Index> = Range<String.Index>(start: start, end: end)
let cleansed:String = string.stringByReplacingOccurrencesOfString("\\s+$",
withString: "",
options: .RegularExpressionSearch,
range: range)
return cleansed
}
Simple. No regular expressions needed.
extension String {
func trimRight() -> String {
let c = reversed().drop(while: { $0.isWhitespace }).reversed()
return String(c)
}
}
so I want to kind of build a "Decrypter", I have a dictionary with the keys being the symbol, and the value the respective value for the symbol, then I have this string that the code is suppose to look into, the translate will be saved in a other string, in this case called output. This is the way I did the loop part, but is not working:
var outputText = " "
for character in textForScan{
for key in gematriaToLetters{
if (gematriaToLetters.keys == textForScan[character]){
outputText.insert(gematriaToLetters.values, atIndex: outputText.endIndex)
}
}
}
You could also consider using map:
let outputText = "".join(map(textForScan) { gematriaToLetters[String($0)] ?? String($0) })
If you don't specify a specific letter in the dictionary it returns the current letter without "converting".
I think you are looking for something like this:
for aCharacter in textForScan {
let newChar = gematrialToLetters["\(aCharacter)"]
outputText += newChar
}
print(outputText)
I have seen many methods for removing the last character from a string. Is there however a way to remove any old character based on its index?
Here is a safe Swift 4 implementation.
var s = "Hello, I must be going"
var n = 5
if let index = s.index(s.startIndex, offsetBy: n, limitedBy: s.endIndex) {
s.remove(at: index)
print(s) // prints "Hello I must be going"
} else {
print("\(n) is out of range")
}
While string indices aren't random-access and aren't numbers, you can advance them by a number in order to access the nth character:
var s = "Hello, I must be going"
s.removeAtIndex(advance(s.startIndex, 5))
println(s) // prints "Hello I must be going"
Of course, you should always check the string is at least 5 in length before doing this!
edit: as #MartinR points out, you can use the with-end-index version of advance to avoid the risk of running past the end:
let index = advance(s.startIndex, 5, s.endIndex)
if index != s.endIndex { s.removeAtIndex(index) }
As ever, optionals are your friend:
// find returns index of first match,
// as an optional with nil for no match
if let idx = s.characters.index(of:",") {
// this will only be executed if non-nil,
// idx will be the unwrapped result of find
s.removeAtIndex(idx)
}
Swift 3.2
let str = "hello"
let position = 2
let subStr = str.prefix(upTo: str.index(str.startIndex, offsetBy: position)) + str.suffix(from: str.index(str.startIndex, offsetBy: (position + 1)))
print(subStr)
"helo"
var hello = "hello world!"
Let's say we want to remove the "w". (It's at the 6th index position.)
First: Create an Index for that position. (I'm making the return type Index explicit; it's not required).
let index:Index = hello.startIndex.advancedBy(6)
Second: Call removeAtIndex() and pass it our just-made index. (Notice it returns the character in question)
let choppedChar:Character = hello.removeAtIndex(index)
print(hello) // prints hello orld!
print(choppedChar) // prints w
So, using Foundation you can use NSCharacterSet to define character sets and test character membership in Strings. I would like to do so without Cocoa classes, but in a purely Swift manner.
Ideally, code could be used like so:
struct ReservedCharacters: CharacterSet {
characters "!", "#", "$", "&", ... etc.
func isMember(character: Character) -> Bool
func encodeCharacter(parameters) { accepts a closure }
func decodeCharacter(parameters) { accepts a closure }
}
This is probably a very loaded question. But I'd like to see what you Swifters think.
You can already test for membership in a character set by initializing a String and using the contains global function:
let vowels = "aeiou"
let isVowel = contains(vowels, "i") // isVowel == true
As far as your encode and decode functions go, are you just trying to get the 8-bit or 16-bit encodings for the Character? If that is the case then just convert them to a String and access there utf8 or utf16 properties:
let char = Character("c")
let a = Array(String(char).utf8)
println() // This prints [99]
Decode would take a little more work, but I know there's a function for it...
Edit: This will replace a character from a characterSet with '%' followed by the character's hex value:
let encode: String -> String = { s in
reduce(String(s).unicodeScalars, "") { x, y in
switch contains(charSet, Character(y)) {
case true:
return x + "%" + String(y.value, radix: 16)
default:
return x + String(y)
}
}
}
let badURL = "http://why won't this work.com"
let encoded = encode(badURL)
println(encoded) // prints "http://why%20won%27t%20this%20work.com"
Decoding, again, is a bit more challenging, but I'm sure it can be done...