here's a part of my code :
let separator = anyWord.indexOf("-")!
if (separator >= 0) {
let res = anyWord[anyWord.characters.index(after: separator)..<anyWord.endIndex] //get an error
//some code
}
I get an error in 'let res' part - Type 'String!' has no subscript members
if I do :
let separator = anyWord.indexOf("-")!
let subStartIndex = anyWord.characters.index(after: separator)
the extension to String :
extension String {
public func indexOf(_ char: Character) -> Int! {
if let idx = self.characters.index(of: char) {
return self.characters.distance(from: self.startIndex, to: idx)
}
return Const.INVALID_VALUE
}
I get error :
String may not be indexed with 'Int", it has variable size elements
You are thinking too complicated, it's pretty easy in Swift 3 using range(of and upperBound
let anyWord = "asdghf-fkgjh"
if let separator = anyWord.range(of:"-") {
let res = anyWord.substring(from: separator.upperBound)
//some code
}
Cast it to string
let test: String
test = "Test-Word"
if let separatorWord = anyWord.range(of: "-")
{
let word = anyWord.substring(from: anyWord.index(after:
separatorWord.lowerBound))
print(word)
}
I like 'pure' swift solution ( no Foundation required )
let anyWord = "asdghf-fkgjh-blablabla--bla"
anyWord.characters.split(separator: "-").forEach { print( String($0)) }
it prints
asdghf
fkgjh
blablabla
bla
Related
How could we convert anyobject to string in swift 3, it's very easy in the older version by using.
var str = toString(AnyObject)
I tried String(AnyObject) but the output is always optional, even when i'm sure that AnyObject is not a optional value.
The compiler suggests that you replace your code with:
let s = String(describing: str)
One other option is available if you have a situation where you want to silently fail with an empty string rather than store something that might not originally be a string as a string.
let s = str as? String ?? ""
else you have the ways of identifying and throwing an error in the answers above/below.
Here's three options for you:
Option 1 - if let
if let b = a as? String {
print(b) // Was a string
} else {
print("Error") // Was not a string
}
Option 2 - guard let
guard let b = a as? String
else {
print("Error") // Was not a string
return // needs a return or break here
}
print(b) // Was a string
Option 3 - let with ?? (null coalescing operator)
let b = a as? String ?? ""
print(b) // Print a blank string if a was not a string
Here's a simple function (repl.it) that will mash any value into a string, with nil becoming an empty string. I found it useful for dealing with JSON that inconsistently uses null, blank, numbers, and numeric strings for IDs.
import Foundation
func toString(_ value: Any?) -> String {
return String(describing: value ?? "")
}
let d: NSDictionary = [
"i" : 42,
"s" : "Hello, World!"
]
dump(toString(d["i"]))
dump(toString(d["s"]))
dump(toString(d["x"]))
Prints:
- "42"
- "Hello, World!"
- ""
Try
let a = "Test" as AnyObject
guard let b = a as? String else { // Something went wrong handle it here }
print(b) // Test
try this -
var str:AnyObject?
str = "Hello, playground" as AnyObject?
if let value = str
{
var a = value as! String
}
OR
var a = str as? String
I want this:
var String1 = "Stack Over Flow"
var desiredOutPut = "SOF" // the first Character of each word in a single String (after space)
I know how to get the first character from a string but have no idea what to do this with this problem.
You can try this code:
let stringInput = "First Last"
let stringInputArr = stringInput.components(separatedBy:" ")
var stringNeed = ""
for string in stringInputArr {
stringNeed += String(string.first!)
}
print(stringNeed)
If have problem with componentsSeparatedByString you can try seperate by character space and continue in array you remove all string empty.
Hope this help!
To keep it more elegant I would make an extension for the swift 3.0 String class with the following code.
extension String
{
public func getAcronyms(separator: String = "") -> String
{
let acronyms = self.components(separatedBy: " ").map({ String($0.characters.first!) }).joined(separator: separator);
return acronyms;
}
}
Afterwords you can just use it like this:
let acronyms = "Hello world".getAcronyms();
//will print: Hw
let acronymsWithSeparator = "Hello world".getAcronyms(separator: ".");
//will print: H.w
let upperAcronymsWithSeparator = "Hello world".getAcronyms(separator: ".").uppercased();
//will print: H.W
SWIFT 3
To avoid the crash when there are multiple spaces between words (i.e. John Smith), you can use something like this:
extension String {
func acronym() -> String {
return self.components(separatedBy: .whitespaces).filter { !$0.isEmpty }.reduce("") { $0.0 + String($0.1.characters.first!) }
}
}
If you want to include newlines as well, just replace .whitespaces with .whitespacesAndNewlines.
Or by using .reduce():
let str = "Stack Over Flow"
let desiredOutPut = str
.components(separatedBy: " ")
.reduce("") { $0 + ($1.first.map(String.init) ?? "") }
print(desiredOutPut)
Note that if you're experiencing error:
Cannot invoke 'reduce' with an argument list of type '(String, (_) -> _)
labelForContext.text = self.components(separatedBy: " ").reduce("") { first, next in
(first) + (next.first.map { String($0) } ?? "")
}
You can use the componentsSeparatedByString() method to get an array of strings. Use " " as the separator.
Since you know how to get the first char of a string, now you just do that for each string in the array.
var String1 = "Stack Over Flow"
let arr = String1.componentsSeparatedByString(" ")
var desiredoutput = ""
for str in arr {
if let char = str.characters.first {
desiredoutput += String(char)
}
}
desiredoutput
By the way, the convention for variable names I believe is camel-case with a lowercase letter for the first character, such as "string1" as opposed to "String1"
Here is the changes in swift3
let stringInput = "Stack Overflow"
let stringInputArr = stringInput.components(separatedBy: " ")
var stringNeed = ""
for string in stringInputArr {
stringNeed = stringNeed + String(string.characters.first!)
}
print(stringNeed)
For the sake of completeness this is a solution with very powerful enumerateSubstrings(in:options:_:
let string = "Stack Over Flow"
var result = ""
string.enumerateSubstrings(in: string.startIndex..<string.endIndex, options: .byWords) { (substring, _, _, _) in
if let substring = substring { result += substring.prefix(1) }
}
print(result)
let inputString = "ABC PQR XYZ"
var stringNeed = ""
class something
{
let splits = inputString.components(separatedBy: " ")
for string in splits
{
stringNeed = stringNeed + String(string.first!)
}
print(stringNeed)
}
Here's the version I used for Swift 5.7 and newer
extension String {
func getAcronym() -> String {
let array = components(separatedBy: .whitespaces)
return array.reduce("") { $0 + String($1.first!)}
}
}
For example:
let test = "hello"
let second_string = "world"
I have a string called test, it contains 5 characters.
Then I have another string: var result:String
I want the first 3 characters in result will be the first 3 characters in test and its rest part will be the content in second_string.
Like
result[0...2] = test[0...2]
result[3...7] = second_string[0...4]
//just pseudo code
This is my extension code:
extension String {
var length: Int {
return self.characters.count
}
subscript (i:Int) -> Character{
return self[self.startIndex.advancedBy(i)]
}
subscript (i: Int) -> String {
return String(self[i] as Character)
}
subscript (r: Range<Int>) -> String {
return substringWithRange(Range(start: startIndex.advancedBy(r.startIndex), end: startIndex.advancedBy(r.endIndex)))
}
}
What should I do ?
let test = "hello"
let second_string = "world"
let range = test.startIndex.advancedBy(0)..<test.startIndex.advancedBy(3)
print(test[range] + second_string)
I am looking for a simple way to remove the 4 characters in the tilesColored String "ment" from the shuffledWord1.
var word1: String = "employment"
var shuffledWord1: String = "melpyoemtn"
var tilesColored: String = "ment"
var characters = Array(tilesColored) // gives ["m","e","n","t"]
let newWord1 = word1.StringByReplacingOccurencesOfString("\(characters[0])", withString:"") // gives "elpyoetn"
stringByReplacingOccurencesOfString only allows 1 character to be checked and removes BOTH m's, so how can I check against all 4 and only remove ONE instance of each to return "melpyo"?
Thanks in advance for any help possible
Swift 3+ version with better performance than the previous top answers. (Because we don't separate into arrays with substrings, which all would need seperate allocations.)
This here just works on the unicode scalar level. You can paste it right into a playground.
import Foundation
extension String {
func removeCharacters(from forbiddenChars: CharacterSet) -> String {
let passed = self.unicodeScalars.filter { !forbiddenChars.contains($0) }
return String(String.UnicodeScalarView(passed))
}
func removeCharacters(from: String) -> String {
return removeCharacters(from: CharacterSet(charactersIn: from))
}
}
let str = "n1o d2i3g4i5t6s!!!789"
let t1 = str.removeCharacters(from: CharacterSet.decimalDigits.inverted)
print(t1) // will print: 123456789
let t2 = str.removeCharacters(from: "0123456789")
print(t2) // will print: no digits!!!
Swift 3 version of Macondo2Seattle's answer, which, I think, is the most elegant solution.
extension String {
func removing(charactersOf string: String) -> String {
let characterSet = CharacterSet(charactersIn: string)
let components = self.components(separatedBy: characterSet)
return components.joined(separator: "")
}
}
Swift 5:
var phrase = "The rain in Spain stays mainly in the plain."
let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
phrase.removeAll(where: { vowels.contains($0) })
// phrase == "Th rn n Spn stys mnly n th pln."
extension String {
func removeCharacters(characters: String) -> String {
let characterSet = NSCharacterSet(charactersInString: characters)
let components = self.componentsSeparatedByCharactersInSet(characterSet)
let result = components.joinWithSeparator("")
return result
}
}
Swift 2.0:
extension String {
func stringByRemovingOnce(chars: String) -> String {
var cs = Set(chars.characters)
let fd = characters.filter { c in
cs.remove(c).map { _ in false } ?? true
}
return String(fd)
}
}
"melpyoemtn".stringByRemovingOnce("ment") // "lpyoem"
Swift 1.2:
extension String {
func stringByRemovingOnce(chars: String) -> String {
var cs = Set(chars)
let fd = filter(self) { c in
cs.remove(c).map { _ in false } ?? true
}
return String(fd)
}
}
"melpyoemtn".stringByRemovingOnce("ment") // "lpyoem"
I have a string composed of words, some of which contain punctuation, which I would like to remove, but I have been unable to figure out how to do this.
For example if I have something like
var words = "Hello, this : is .. a string?"
I would like to be able to create an array with
"[Hello, this, is, a, string]"
My original thought was to use something like words.stringByTrimmingCharactersInSet() to remove any characters I didn't want but that would only take characters off the ends.
I thought maybe I could iterate through the string with something in the vein of
for letter in words {
if NSCharacterSet.punctuationCharacterSet.characterIsMember(letter){
//remove that character from the string
}
}
but I'm unsure how to remove the character from the string. I'm sure there are some problems with the way that if statement is set up, as well, but it shows my thought process.
Xcode 11.4 • Swift 5.2 or later
extension StringProtocol {
var words: [SubSequence] {
split(whereSeparator: \.isLetter.negation)
}
}
extension Bool {
var negation: Bool { !self }
}
let sentence = "Hello, this : is .. a string?"
let words = sentence.words // ["Hello", "this", "is", "a", "string"]
String has a enumerateSubstringsInRange() method.
With the .ByWords option, it detects word boundaries and
punctuation automatically:
Swift 3/4:
let string = "Hello, this : is .. a \"string\"!"
var words : [String] = []
string.enumerateSubstrings(in: string.startIndex..<string.endIndex,
options: .byWords) {
(substring, _, _, _) -> () in
words.append(substring!)
}
print(words) // [Hello, this, is, a, string]
Swift 2:
let string = "Hello, this : is .. a \"string\"!"
var words : [String] = []
string.enumerateSubstringsInRange(string.characters.indices,
options: .ByWords) {
(substring, _, _, _) -> () in
words.append(substring!)
}
print(words) // [Hello, this, is, a, string]
This works with Xcode 8.1, Swift 3:
First define general-purpose extension for filtering by CharacterSet:
extension String {
func removingCharacters(inCharacterSet forbiddenCharacters:CharacterSet) -> String
{
var filteredString = self
while true {
if let forbiddenCharRange = filteredString.rangeOfCharacter(from: forbiddenCharacters) {
filteredString.removeSubrange(forbiddenCharRange)
}
else {
break
}
}
return filteredString
}
}
Then filter using punctuation:
let s:String = "Hello, world!"
s.removingCharacters(inCharacterSet: CharacterSet.punctuationCharacters) // => "Hello world"
let charactersToRemove = NSCharacterSet.punctuationCharacterSet().invertedSet
let aWord = "".join(words.componentsSeparatedByCharactersInSet(charactersToRemove))
An alternate way to filter characters from a set and obtain an array of words is by using the array's filter and reduce methods. It's not as compact as other answers, but it shows how the same result can be obtained in a different way.
First define an array of the characters to remove:
let charactersToRemove = Set(Array(".:?,"))
next convert the input string into an array of characters:
let arrayOfChars = Array(words)
Now we can use reduce to build a string, obtained by appending the elements from arrayOfChars, but skipping all the ones included in charactersToRemove:
let filteredString = arrayOfChars.reduce("") {
let str = String($1)
return $0 + (charactersToRemove.contains($1) ? "" : str)
}
This produces a string without the punctuation characters (as defined in charactersToRemove).
The last 2 steps:
split the string into an array of words, using the blank character as separator:
let arrayOfWords = filteredString.componentsSeparatedByString(" ")
last, remove all empty elements:
let finalArrayOfWords = arrayOfWords.filter { $0.isEmpty == false }
NSScaner way:
let words = "Hello, this : is .. a string?"
//
let scanner = NSScanner(string: words)
var wordArray:[String] = []
var word:NSString? = ""
while(!scanner.atEnd) {
var sr = scanner.scanCharactersFromSet(NSCharacterSet(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKMNOPQRSTUVWXYZ"), intoString: &word)
if !sr {
scanner.scanLocation++
continue
}
wordArray.append(String(word!))
}
println(wordArray)