2

I am attempting to use rangeOfCharacter to create an app, but am unable to understand its documentation:

func rangeOfCharacter(from: CharacterSet, options: 
String.CompareOptions, range: Range<String.Index>?)

-Finds and returns the range in the String of the first character from 
a given character set found in a given range with given options.

Documentation link: https://developer.apple.com/documentation/swift/string#symbols

I am working on an exercise to create a function which will take in a name and return the name, minus any consonants before the first vowel. The name should be returned unchanged if there are no consonants before the first vowel.

Below is the code I have so far:

func shortNameFromName(name: String) -> String {
    var shortName = name.lowercased()
    let vowels = "aeiou"
    let vowelRange = CharacterSet(charactersIn: vowels)
    rangeOfCharacter(from: vowels, options: shortName,
                 range: substring(from: shortName[0]))

Any help is much appreciated. Apologies for the newbie mistakes.

Cali_Ranger
  • 59
  • 1
  • 6

4 Answers4

1

Use this code with a regular expression your problem is solved

Improved

func shortNameFromName(name: String) -> String {
    do{
        let regex2 = try NSRegularExpression(pattern: "[a|e|i|o|u].*", options:[.dotMatchesLineSeparators])
        if let result = regex2.firstMatch(in: name.lowercased(), options: .init(rawValue: 0), range: NSRange(location: 0, length: NSString(string: name).length))
        {
            return String(NSString(string: name).substring(with: result.range))
        }
    }
    catch
    {
        debugPrint(error.localizedDescription)
    }
    return ""
}

Tested

debugPrint(self.shortNameFromName(name: "yhcasid")) //test1
debugPrint(self.shortNameFromName(name: "ayhcasid")) //test2
debugPrint(self.shortNameFromName(name: "abc")) // working thanks to @MartinR

Console Log

test1 result

"asid"

test2 result

"ayhcasid"

test3 result

"abc"

Hope this helps

Community
  • 1
  • 1
Reinier Melian
  • 20,519
  • 3
  • 38
  • 55
1

I hate Swift ranges. But hopefully things will get better with Swift 4.

let name = "Michael"
var shortName = name.lowercased()
let vowels = "aeiou"
let vowelSet = CharacterSet(charactersIn: vowels)

let stringSet = shortName
if let range = stringSet.rangeOfCharacter(from: vowelSet, options: String.CompareOptions.caseInsensitive) 
{
    let startIndex = range.lowerBound

    let substring = name.substring(from: range.lowerBound)
    print(substring)
}
Bista
  • 7,869
  • 3
  • 27
  • 55
Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
1

You are passing completely wrong arguments to the method.

rangeOfCharacter accepts 3 arguments. You passed in the character set correctly, but the last two arguments you passed makes no sense. You should pass a bunch of options as the second argument, instead you passed in a string. The third argument is supposed to be a Range but you passed the return value of a substring call.

I think rangeOfCharacter isn't suitable here. There are lots more better ways to do this. For example:

func shortNameFromName(name: String) -> String {
    return String(name.characters.drop(while: {!"aeiou".characters.contains($0)}))
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • 1
    you might want to edit this: `String.characterView` has no member / function named `drop`. – Michael Dautermann Jul 28 '17 at 05:37
  • @MichaelDautermann I tried this in the playground and it compiles and produces the expected result. `drop` is declared in `Collection`, which `CharacterView` conforms to, right? Or are you not using Swift 3? – Sweeper Jul 28 '17 at 05:39
  • I'm using Xcode 8.2 and a playground, and my auto complete is showing me `dropFirst` and `dropLast` after `characters`, but no `drop`. Oh well, if you say it works for you, maybe it will work for the O.P. – Michael Dautermann Jul 28 '17 at 05:42
  • @MichaelDautermann: `drop(while:)` was added in Swift 3.1 (Xcode 8.3.3): https://github.com/apple/swift-evolution/blob/master/proposals/0045-scan-takewhile-dropwhile.md. – Martin R Jul 28 '17 at 07:45
  • @Sweeper: I would write the closure as `{!"aeiou".characters.contains($0)}` – Martin R Jul 28 '17 at 08:38
  • 1
    @MartinR Edited. – Sweeper Jul 28 '17 at 11:47
0

Swift 3 replace your code here..

func shortNameFromName(name: String) -> String {
var shortName = name.lowercased()
let newstring = shortName
let vowels: [Character] = ["a","e","i","o","u"]
for i in shortName.lowercased().characters {
    if vowels.contains(i) {
        break
    }
    else {
        shortName =  shortName.replacingOccurrences(of: "\(i)", with: "")
    }

}

if shortName != "" {
    return shortName
}
else
{
    return newstring
}
Raksha Saini
  • 604
  • 12
  • 28