-1

I'm new at Swift, could anyone explain to me why I'm keep getting this problem. I'm using Xcode 6.4, but here is my question I hope I cleared it up but I needed my Function to takes in Large String then returns Tuple(numVowels, numConsonants) Count the number of words that start with consonants/vowels Return the Tuple and print the result of the function call. I did not need for it to count characters, only first character of each word. I create an for loop which will switch everything to lowercase. But now I'm stuck.

func count(string: String) -> (Vowels:Int, Consonants:Int) {
    var Vowels = 0, Consonants = 0
    for character in string {
        switch String(character).lowercaseString {
            case "a","e","i","o","u":
              ++Vowels
            case "b","c","d","e","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z":
            ++Consonants
        default: break
        }

    }
    return (Vowels, Consonants)
}
NOVA99
  • 29
  • 2
  • 10
Jet Lagg
  • 11
  • 1
  • 3
  • are you using swift 2 in XCode 7 beta 5? – ielyamani Aug 12 '15 at 00:18
  • I'm using Swift in Xcode – Jet Lagg Aug 12 '15 at 00:24
  • 2
    Judging from the answers provided thus far, I'm gathering that no one is correctly understanding your question. Please clarify. Give an example input, what you're getting for output, and what you're expecting for output. – Rob Aug 12 '15 at 00:25
  • and could you please clarify what you want to do exactly? – ielyamani Aug 12 '15 at 00:27
  • Im using Xcode 6.4, but here is my question I hope I cleared it up but I needed my Function to takes in Large String then returns Tuple(numVowels, numConsonants) Count the number of words that start with consonants/vowels Return the Tuple and print the result of the function call. I did not need for it to count characters, only first character of each word. @Carpsen90 – Jet Lagg Aug 12 '15 at 00:36
  • 1
    @JetLagg Please integrate these clarifications in the original question. Click on "edit" underneath your question, and then update the original question. – Rob Aug 12 '15 at 00:41
  • BTW, if you're using Xcode 6.4, why is this question tagged Swift 2? I assume you're using Swift 1.2. – Rob Aug 12 '15 at 01:30
  • FYI, you might want to remove `e` from your list of consonants. Sure, it will be caught by the vowel check first, but it doesn't seem right to include `e` in both lists. – Rob Aug 12 '15 at 02:22
  • Yes I removed it thanks, I notice that as well @rob – Jet Lagg Aug 12 '15 at 02:28

3 Answers3

1

The problem there is the name that you choose for your method. Try any name other than count and you should be fine.

edit/update: Swift 4

func countCharacteres(_ string: String) -> (vowels: Int, consonants: Int) {
    var vowels = 0, consonants = 0
    for character in string {
        switch String(character).lowercased() {
        case "a","e","i","o","u":
            vowels += 1
        case "b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z":
            consonants += 1
        default:
            break
        }
    }
    return (vowels, consonants)
}

let name = "Dromel"
countCharacteres(name).vowels      // 2
countCharacteres(name).consonants  // 4

If you want to count only the first letter of each word you need to break your string into an array of words and extract the lowercase of each first letter as follow:

extension StringProtocol where Index == String.Index {
    var range: Range<Index> { return startIndex..<endIndex }
    var words: [String] {
        var words: [String] = []
        enumerateSubstrings(in: range, options: .byWords) { word, _, _, _ in words.append(word!) }
        return words
    }
}
extension StringProtocol  where Index == String.Index {
    var firstCharacterCount: (vowels: Int, consonants: Int) {
        var vowels = 0, consonants = 0
        for first in words.compactMap({$0.lowercased().first}) {
            switch first {
            case "a","e","i","o","u":
                vowels += 1
            case "b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z":
                consonants += 1
            default: break
            }
        }
        return (vowels, consonants)
    }
}

let sentence = "Hello World. Apple."
let counter =  sentence.firstCharacterCount
counter.vowels      // 1
counter.consonants  // 2

Note that the extension should be placed in a new Swift file inside your project.

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • I read his question as saying "I'm getting counts of all the letters, and I only want the first letter of each word." I think you're answering a different question. – Rob Aug 12 '15 at 00:20
  • @Rob you are correct. But he still need to choose another name for his method. May be that was his main problem – Leo Dabus Aug 12 '15 at 00:22
  • 1
    Don't get me wrong: I agree that he would be well advised to change the name. That just has nothing to do with the question, IMHO. – Rob Aug 12 '15 at 00:24
  • actually no @LeoDabus , see my answer. But the question is still not clear enough. – ielyamani Aug 12 '15 at 00:24
  • Okay I change my method but I'm still getting the count for each characters instead of only the first character of each word. @Rob – Jet Lagg Aug 12 '15 at 00:28
  • @JetLagg Oh, you should update your question to include the current vs. expected output because your original question wasn't clear at all... – Lyndsey Scott Aug 12 '15 at 00:32
  • Looks good, but I'd recommend (1) using `componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())` (separating by punctuation seems irrelevant in this case, but separating by newline seems very necessary), and (2) filtering before the loop so there are no unnecessary iterations. – Lyndsey Scott Aug 12 '15 at 01:02
  • @LyndseyScott feel free to edit and improve the answer – Leo Dabus Aug 12 '15 at 01:05
  • 1
    Thanks everyone that's what it was I needed to break up the string into and array of words @LyndseyScott, LeoDabus – Jet Lagg Aug 12 '15 at 01:36
1

if you are using swift 2 :

just change this line

for character in string {

to

for character in string.characters {

and it would work just fine

count("hello") // (.0 2, .1 3)
ielyamani
  • 17,807
  • 10
  • 55
  • 90
  • This is correct, if he wanted to convert that to Swift 2, that's how he'd do it. But I do not believe that is the question at hand. – Rob Aug 12 '15 at 00:25
0

Another option is to use regular expression to retrieve the first letter of every word. The \b option is used to find word boundaries, and \w is a single word character. Thus, once you escape the back slashes, \\b\\w will capture the first letter immediately following a word boundary (a.k.a., the first letter of every word):

func countLetters(string: String) -> (vowels: Int, consonants: Int) {
    var vowels = 0, consonants = 0
    let regex = NSRegularExpression(pattern: "\\b\\w", options: nil, error: nil)
    regex?.enumerateMatchesInString(string, options: nil, range: NSMakeRange(0, count(string))) { matches, flags, stop in
        switch (string as NSString).substringWithRange(matches.range).lowercaseString {
        case "a","e","i","o","u":
            ++vowels
        case "b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z":
            ++consonants
        default: break
        }
    }
    return (vowels, consonants)
}

--

If you want to handle accented characters (e.g. "étude"), you might want to remove those diacritics first:

func countLetters(string: String) -> (vowels: Int, consonants: Int) {
    let convertedString = NSMutableString(string: string)
    CFStringTransform(convertedString, nil, kCFStringTransformStripCombiningMarks, Boolean(0))

    var vowels = 0, consonants = 0
    let regex = NSRegularExpression(pattern: "\\b\\w", options: nil, error: nil)
    regex?.enumerateMatchesInString(convertedString as String, options: nil, range: NSMakeRange(0, convertedString.length)) { matches, flags, stop in
        switch convertedString.substringWithRange(matches.range).lowercaseString {
        case "a","e","i","o","u":
            ++vowels
        case "b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z":
            ++consonants
        default: break
        }
    }
    return (vowels, consonants)
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044