Replace just the first character in a string | Swift - arrays

I'm trying to replace the just first character of a string. Using this answer, I'm able to replace all current characters with the one I want, but what I really need is to only replace the character if it's at the start of a word.
For example, replace c with t:
Original String: Jack is cool
New Sting: Jack is tool
My Current Code:
let aString: String = "jack is cool"
let toArray: Array = aString.componentsSeparatedByString(" ")
let newString: String = aString.stringByReplacingOccurrencesOfString("c", withString: "t", options: NSStringCompareOptions.LiteralSearch, range: nil)
This would print out as:
"jatk is tool"
I assume I have to do something with the range attribute in the newString.

I would use regex. \\b called word boundary which matches between a word character and a non-word character. You may also use negative lookbehind instead of \\b like (?<!\\S)c
var regex:NSRegularExpression = NSRegularExpression(pattern: "\\bc", options: NSRegularExpressionOptions.CaseInsensitive, error: &ierror)!
var modString = regex.stringByReplacingMatchesInString(myString, options: nil, range: NSMakeRange(0, stringlength), withTemplate: "t")

var aString = 'jack is cool';
var newString = aString.replace('c','t');

var a
var oldString = 'Jack is cool';
var newString = oldString.split(' ');
var x = newString[newString.indexOf('cool')].toString();
x = x.replace('c','t');
newString.splice(newString.indexOf('cool'),1,x);
newString = newString.join(' ').toString();
alert(newString);

You can define your range to start and end at the startIndex to make sure it replaces only occurences at the first character of the string:
let coolString = "Cool"
let newString = coolString.stringByReplacingOccurrencesOfString("C", withString: "T", options: [], range: coolString.startIndex...coolString.startIndex)
You can use String method replace() to replace only the first character of a String
var str = "Cool"
str.replaceRange(str.startIndex...str.startIndex, with: "T")
print(str) // "Tool"
To apply it only to the last word:
var str = "Jack is Cool"
var words = str.componentsSeparatedByString(" ")
if !words.isEmpty {
if !words[words.count-1].isEmpty {
words[words.count-1].replaceRange(str.startIndex...str.startIndex, with: "T")
print( words.last!) // "Tool\n"
}
}
let sentence = words.joinWithSeparator(" ") // "Jack is Tool"

Related

How can I remove the parenthesis from a regex result in swift 5?

this is my first time with swift and I have some troubles with an school project
I have the following:
var tokens = ["if", "for", "(", ")", "while", "var"]
var test = "if, identifier, for, (, ), while, var1, 3var, ResultVariable, i dentifier";
var lineas = [String]()
I converted the "test" into "lineas" array:
lineas = data.components(separatedBy: ", ")
Then I created the following regex pattern to find ids in the "test" string (id is any variable name)
//id: any word that begins with lowercase and can have 0 or more alphanumerics characters
let id = "[a-z][\\w]*"
let regexId = try! NSRegularExpression(pattern: id, options: [])
The result of the regex is saved in a String and then into in array
let idString = regexId.stringByReplacingMatches(in: test, options: [], range: NSRange(location: 0, length: test.count), withTemplate: "($0)")
let idArray = idString.components(separatedBy: "\n")
Then I try to compare the "idArray" with the "tokens" array to obtain only the ids
let idResults = idArray.filter({!tokens.contains($0)})
print("\nID found\n")
for ids in idResults{
print(ids)
}
But the output I got is:
ID found:
["(if)", "(for)", "(identifier)", "(for)", "(while)", "(var1)", "3(var)", "R(esultVariable)", "(i) (dentifier)"]
When the output I need is:
ID found:
["identifier, var1"]
And this is because "3var, ResultVariable, i dentifier" are not identifiers because they start with numer, uppercase or have an space
Here is a solution not based on regex that instead uses the filter function in different ways
var tokens = ["if", "for", "(", ")", "while", "var"]
var test = "if, identifier, for, (, ), while, var1, 3var, ResultVariable, i dentifier";
var lineas = test.components(separatedBy: ", ")
let identifiers = lineas
.filter {!tokens.contains($0)} // Not a token
.filter { // Starts with lowercase letter
guard let first = $0.first else { return false }
return first.isLetter && first.isLowercase
}
.filter { $0.rangeOfCharacter(from: .whitespaces) == nil } // No whitespace
Of course the above can be merged in to one call of filter but I left it as 3 separate calls for clarity.

Swift: Filter string by using start with

I have an array as follows:
let array = ["sam", "andrew", "character"]
And I want to get every element in the array that starts with a character I type
My problem is when i type "a" the output is "sam", "andrew", and "character".
I want to get the output to only be "andrew". (The string must start from left to right when searching)
You need to filter your array using hasPrefix
var names = ["sam", "andrew", "character"]
var searchString = "a"
let filteredNames = names.filter({ $0.hasPrefix(searchString) })
print(filteredNames)
You must use string.hasPrefix(string)
You can try to use this in Swift 5:
let filteredNames = names.filter{$0.range(of: searchText, options: [.caseInsensitive, .anchored]) != nil}

Swift 4 array issue in changing text colour

I have a string and I want to change colors of two words in that string. So, I created a function
func setup()
{
let main_string = "By continuing you agree to our Term of use and Privacy Policy "
var string_to_color = ["By continuing you agree to our","and"]
for i in 0..<2
{
let range = (main_string as NSString).range(of: string_to_color[i])
let attributedString = NSMutableAttributedString.init(string:main_string)
attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.black , range: range)
privacyL.attributedText = attributedString
}
But, it only changes the colour for the second word and not for the first one.
Can anyone help?
let main_string = "By continuing you agree to our Term of use and Privacy Policy "
var string_to_color = ["By continuing you agree to our","and"]
for i in 0..<2
{
let range = (main_string as NSString).range(of: string_to_color[i])
let attributedString = NSMutableAttributedString.init(string:main_string)
attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.black , range: range)
privacyL.attributedText = attributedString
}
You are overriding each time privacyL.attributedText, so you'll get only the "result" of last iteration.
Instead, do:
let attributedString = NSMutableAttributedString.init(string:main_string)
for i in 0..<2
{
let range = (main_string as NSString).range(of: string_to_color[i])
attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.black , range: range)
}
privacyL.attributedText = attributedString
Now, next issues:
Don't do a loop for i in 0..<2, instead use at least the count of string_to_color (or a for each loop). If tomorrow you add a string in it or remove one, you'll encounter an issue.
Also range(of:) will return the first occurence found, so if you have:
let main_string = "and and"
var string_to_color = ["something", "and"]
only the first "and" will be colored.
You have then to iterate or use a NSRegularExpression.
Here is a related question: Color all occurrences of string in swift
Just want to add to Larme's answer. You can create extension of String, which will be responsible for string coloring
extension String {
func colored(_ strings: [String], with color: UIColor) -> NSAttributedString {
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: self)
for string in strings {
let range = (self as NSString).range(of: string)
attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: color , range: range)
}
return attributedString
}
}
And now you can use it anywhere in your code, like this:
let main_string = "By continuing you agree to our Term of use and Privacy Policy "
let string_to_color = ["By continuing you agree to our","and"]
privacyL.attributedText = main_string.colored(string_to_color, with: UIColor.red)

Swift 3 simple search engine

I have an array of Strings containing user inputted values. I have a string containing several words (the number of words in the string varies). I want to increment an Int every time one of the words in the string matches a word in the array.
I'm using this method:
var searchWordsArr: [String] = [] \\filled by user input
var message: String = "" \\random number of words
var numRelevantWords = 0
var i = 0
while i < self.searchWordsArr.count {
i+=1
if message.contains(self.searchWordsArr[i-1]) {
numRelevantWords += 1
}
}
In my first example, the string contained 25 words and the array contained 3 words. The 3 words came up a total of 12 times in the string. Using the above method, the value of numRelevantWords was 2.
I would use regex. Some day soon, Swift will have native regular expressions. But until it does, you have to resort to Foundation:
let words = ["the", "cat", "sat"]
let input = "The cat sat on the mat and the mat sat on the catastrophe"
var result = 0
let pattern = "\\b(" + words.joined(separator:"|") + ")\\b"
do {
let regex = try NSRegularExpression(pattern: pattern, options: .caseInsensitive)
let match = regex.matches(in: input, options: [], range: NSRange(location: 0, length: input.utf16.count))
result += match.count // 7, that's your answer
} catch {
print("illegal regex")
}
Add them to a NSCountedSet:
let searchWords = NSCountedSet()
searchWords.add("Bob")
searchWords.add("John")
searchWords.add("Bob")
print(searchWords.count(for: "Bob")) // 2
"pure" Swift (no Foundation)
let message = "aa bb aaaa ab ac aa aa"
let words = message.characters.split(separator: " ").map(String.init)
let search:Set = ["aa", "bb", "aa"]
let found = words.reduce(0) { (i, word) -> Int in
var i = i
i += search.contains(word) ? 1 : 0
return i
}
print(found, "word(s) from the message are in the search set")
prints
4 word(s) from the the message are in the search set
UPDATE (see discussion)
using Set
var search: Set<String> = [] // an empty set with Element == String
search.insert("aa") // insert word to set
using Array
var search: Array<String> = [] // an empty array
search.append("aa") // append word to array
maybe you are looking for
let message = "the cat in the hat"
let words = message.characters.split(separator: " ").map(String.init)
let search:Set = ["aa", "bb", "pppp", "the"]
let found = search.reduce(0) { (i, word) -> Int in
var i = i
i += words.contains(word) ? 1 : 0
return i
}
print(found, "word(s) from the search set found in the message")
prints
1 word(s) from the search set found in the message
if you would like to produce the same as with accepted answer
let words = ["the", "cat", "sat"]
let input = "The cat sat on the mat and the mat sat on the catastrophe"
let inputWords = input.lowercased().characters.split(separator: " ").map(String.init)
let found = inputWords.reduce(0) { (i, word) -> Int in
var i = i
i += words.contains(word.lowercased()) ? 1 : 0
return i
}
print(found, "word(s) from the search set found in the message")
prints
7 word(s) from the search set found in the message

How to store characters in string into an Array using Swift

Using Swift. How do I take a String and separate each character into an array?
var someString = "123"
var someArray = []
someArray[0] = "1"
someArray[1] = "2"
someArray[2] = "3"
Array has constructor that takes String and produce array of characters.
let someString = "abcde"
let array = Array(someString)
yes there are many ways to achieve this task old and best way is to use for in loop in the following way
var someString = "123"
var someArray : Array<Character> = []
for character in someString {
someArray.append(character)
}
println(someArray)

Resources