How to remove zero width spaces from string in Swift? [duplicate] - ios

This question already has answers here:
How to remove special characters from string in Swift 2?
(6 answers)
Closed 3 years ago.
I need to filter invisible character from a string. In the attached screen shot, string "​Cilantro" has some hidden character and when i get count of this before and after removing hidden character it shows different character count.
I just want to filter invisible characters not special characters, for example I dont want to filter á, ã è etc characters.
Note: I removed hidden characters using "delete" button.
For the reference I am adding here the String with invisible character: "​Cilantro". I am not sure if it will show at your end too.

Swift 5 or later
You can use new Character isLetter property
let del = Character(UnicodeScalar(127)!)
let string = "Cilantro\(del)\(del)"
print(string.count) // "10\n"
let filtered = string.filter { $0.isLetter }
print(filtered.count) // "8\n"
let string = "cafe\u{301}"
let filtered = string.filter { $0.isLetter }
print(filtered) // "café"
If you just want to remove zero width spaces from your string you can do as follow:
extension Character {
static let zeroWidthSpace = Self(.init(0x200B)!)
var isZeroWidthSpace: Bool { self == .zeroWidthSpace }
}
extension Bool {
var negated: Bool { !self }
}
let str = "​Cilantro"
print(str.count) // 9
let filtered = str.filter(\.isZeroWidthSpace.negated)
print(filtered.count) // 8

Related

How to capitalize each alternate character of a string?

Lets say there is a string "johngoestoschool" it should become "JoHnGoEsToScHoOl" and incase if there is a special character in between it should ignore it for example given string "jo$%##hn^goe!st#os&choo)l" answer should be "Jo$%##Hn^GoE!sT#oS&cHoO)l"
From this answer, we in order to iterate we can do:
let s = "alpha"
for i in s.characters.indices[s.startIndex..<s.endIndex]
{
print(s[i])
}
Why can't we print the value of "i" here?
When we do i.customPlaygroundQuickLook it types int 0 to int4.
So my idea is to
if (i.customPlaygroundQuickLook == 3) {
s.characters.currentindex = capitalized
}
Kindly help
This should solve your function, the hard part is just checking weather the character is letters or not, using inout and replace range would give better performance:
func altCaptalized(string: String) -> String {
var stringAr = string.characters.map({ String($0) }) // Convert string to characters array and mapped it to become array of single letter strings
var numOfLetters = 0
// Convert string to array of unicode scalar character to compare in CharacterSet
for (i,uni) in string.unicodeScalars.enumerated() {
//Check if the scalar character is in letter character set
if CharacterSet.letters.contains(uni) {
if numOfLetters % 2 == 0 {
stringAr[i] = stringAr[i].uppercased() //Replace lowercased letter with uppercased
}
numOfLetters += 1
}
}
return stringAr.joined() //Combine all the single letter strings in the array into one string
}

Is there a way to capitalize letters randomly in a sentence in Swift? [duplicate]

This question already has an answer here:
How to randomize the case of letters in a string in Swift? [closed]
(1 answer)
Closed 6 years ago.
Just want a way to capitalize letters in a sentence randomly. Is it possible?
Try this,
var string: String = "your string"
var chars: [Any] = []
var letterIndexes: [Any] = []
for i in 0..<string.characters.count {
var ch: unichar = string[i]
// add each char as a string to a chars collection
chars.append("\(ch)")
// record the index of letters
if CharacterSet.letters.characterIsMember(ch) {
letterIndexes.append((i))
}
}
select randomly from the letterIndexes to determine which letters will be upper case. Convert the member of the chars array at that index to uppercase.
var charsToUppercase: Int = 12
var i = 0
while i < charsToUppercase && letterIndexes.count {
var randomLetterIndex: Int? = arc4random_uniform(((letterIndexes.count) as? u_int32_t))
var indexToUpdate = CInt(letterIndexes[randomLetterIndex])
letterIndexes.remove(at: randomLetterIndex)
chars[indexToUpdate] = chars[indexToUpdate].uppercased()
i += 1
}
ow all that's left is to join the chars array into a string.
var result: String = (chars as NSArray).componentsJoined(byString: "")
print("\(result)")
Refer this link for more information.

How to format UILabel text to locale specific NSNumberFormatterStyle.DecimalStyle

I have a UILabel to show input text (which has decimal numbers). What I am trying to do is, that the UILabel text can be shown as per locale. E.g.-
"1234.56" should be shown as "1,234.56" for US locale, "1.234,56" for DE (Germany) locale and so on.
Below is what I have done to achieve this -
NSNumberFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
NSNumberFormatter.locale = NSLocale(localeIdentifier: language)
NSNumberFormatter.maximumFractionDigits = 16
let displayVal: Double = NSNumberFormatter.numberFromString(displayText.text!).doubleValue
displayText.text = NSNumberFormatter.stringFromNumber(displayVal)
Where displayText is the UILabel to display input.
It works fine until 4 digits i.e. "1234" was shown as "1,234" (for US locale). But as soon as 5th digit gets added, nil returned for displayVal constant variable.
I could guess from the function definition that there is failure in formatting displayText text string which may be "1,2345" when numberFromString tried to format it as per US locale but failed as this does not comply to US locale format.
Can anyone suggest a way to fix this or nicer way of implementation?
You can do something like the following, namely strip out any thousands separators, get a number from that, and then reformat with the thousands separator:
#IBAction func didEditingChanged(_ sender: UITextField) {
guard let text = sender.text else { return }
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
// get thousands separator
let thousandsSeparator = formatter.groupingSeparator ?? ","
// strip thousands separators out
let stripped = String(text.filter { return String($0) != thousandsSeparator })
// now, re-insert them, if any
if let number = formatter.numberFromString(stripped) {
sender.text = formatter.stringFromNumber(number)
}
}
Assuming you're hooking this up to "Editing Changed" so that it's constantly updated, this introduces a few issues. For example, to enter the trailing decimal place, you might have to manually check for that and allow that to be preserved:
#IBAction func didEditingChanged(_ sender: UITextField) {
guard let text = sender.text else { return }
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
// get thousands separator
let thousandsSeparator = formatter.groupingSeparator ?? ","
// strip thousands separators out
let stripped = String(text.filter { return String($0) != thousandsSeparator })
// see if decimal place found, and if so, set fractional digits accordingly
let decimalSeparator = formatter.decimalSeparator ?? "."
var fractionalDigits: Int?
if let decimalSeparatorIndex = text.range(of: decimalSeparator)?.lowerBound {
fractionalDigits = text[decimalSeparatorIndex...].count(of: "0123456789")
formatter.minimumFractionDigits = fractionalDigits!
}
guard
let number = formatter.number(from: stripped),
var result = formatter.string(from: number)
else {
// do whatever is appropriate if string isn't a number at all
return
}
// re-add trailing decimal place only if decimal separator was found, but no fractional digits were
if fractionalDigits == 0 {
result += decimalSeparator
}
// update text field
sender.text = result
}
Note, that uses this little extension:
extension StringProtocol {
func count(of string: String) -> Int {
return reduce(0) { $0 + (string.contains($1) ? 1 : 0) }
}
}
There are many other refinements you could tackle. For example, if the user is not at the end of the text field when they edit, this will reset the selectedTextRange. You also should probably implement shouldChangeCharactersIn to make sure that you cannot enter value at all where stripped would fail. Etc.
But hopefully this illustrates one approach for capturing text input and updating the result with the formatted decimal number.
For Swift 2 rendition, see previous revision of this answer.
You need to make sure the number formatter matches the strings that you pass to it. If there is any mismatch, it is going to return nil, and the doubleValue call is going to return 0.
If you have strings formatted for the US, with a grouping separator of a comma, then you should set the groupingSeparator property of the number formatter to a comma. Then the formatter should handle input strings like "1,234". As you say, "1,2345" is not a normal US format for displaying a number.
You might need to change the groupingSize setting as well (The string "1,2345" would have a groupingSize of 4, if I'm not mistaken.
Where are the strings you are parsing coming from? Do you know what locale they use? Is the user entering "1,2345" on a device that is set up using the en-US locale"? If so, why? That's not normal formatting for US English.

Swift Checking if entire word is present in a string [duplicate]

This question already has answers here:
Detect whole word in NSStrings
(4 answers)
Closed 6 years ago.
What I want to do is to check if an entire word is present in a string. Let me give you an example.
let mainString = "this is a my string"
let searchString = "str"
if mainString.containsString(searchString) {
}
Here this condition will be true but I do not want this. I want it to be true when either "this" or "is" or "a" or "my" or "string" is searched in the mainString meaning I want to compare the whole word not the characters within the string. I hope I have elaborated it.
// The following method will return a string without punctuation and non-required stuff characters
Source of information : How to remove special characters from string in Swift 2?
func removeSpecialCharsFromString(mainString) -> String {
let okayChars : Set<Character> =
Set("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLKMNOPQRSTUVWXYZ".characters)
return String(text.characters.filter {okayChars.contains($0) })
}
let stringWithoutSpecialChars = removeSpecialCharsFromString(mainString)
// Source of info : Chris's answer on this page
let components = stringWithoutSpecialChars.componentsSeparatedByString(" ")
for component in components {
print(component)
}
You have to use a Regex like that :
NSString *pattern = #"\\str\\b";
NSRange range = [text rangeOfString:pattern options:NSRegularExpressionSearch|NSCaseInsensitiveSearch];
The \b at the end of the pattern do what you want, it will match only whole words.
I would recommend splitting your string into components and seeing if a component matches your string. Below is a method that uses components to check if any word matches a given search term.
func isTermInString(term:String, stringToSearch:String) -> Bool {
let components = stringToSearch.componentsSeparatedByString(" ")
for component in components {
if component == term {
return true
}
}
return false
}

How to put variable inside text field AND how to convert all elements to string NOT just 1 at a time?

This is a follow up question to How to have 10 characters total and make sure at least one character from 4 different sets is used randomly
this is my code so far
let sets = ["ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz", "1234567890", "\"-/:;()$&#.,?!'[]{}#%^\\|~<>€£¥•.,"].map { Array($0.characters) }
var randoms = sets.map { $0.random }
while randoms.count < 10 {
randoms.append(sets.random.random)
}
var convertedElems = String()
let something = randoms.shuffled()
for key in something {
convertedElems = String(key)
}
uniqueRoomID.text = randoms.shuffled()
Im getting an error saying cannot convert [Element] to type "String"
So i tried a for loop but that only converts 1 at a time when its supposed to do all 10
my other question is i tried storing a character in a variable and then setting a text field.text equal to that variable and nothing happened
What am i doing wrong here
Your randoms.shuffled() is an array of Characters. You need to convert it back into a String.
Change this:
uniqueRoomID.text = randoms.shuffled()
to this:
uniqueRoomID.text = String(randoms.shuffled())

Resources