计算列表中名字的第一个字母

时间:2015-01-21 00:15:27

标签: ios arrays function swift dictionary

我正在尝试创建一个以列表作为参数的函数,并返回名字作为列表的首字母类型,以及这些字母的数量,例如,如果我的列表如下所示:

let thisList:[String] = ["Roman", "Serial", "Thomas", "Peter", "Pan", "Other", "Peter", "Remy"]

我希望我的函数的输出看起来像这样:

["r": 2, "o": 1, "p": 3, "s": 1, "t": 1]

我的功能目前看起来像这样:

func listCounter(usernames: [String])->Dictionary<String,Int>{

    var countDict : [ String : Int ] = [:]
    var list = [String](countDict.keys)

    for user in usernames{

        let index = advance(user.startIndex, 0)

        //Retrieving the first letter of the name and converting it to a string
        var letter = "\(user[index])" as String
        letter = letter.lowercaseString

        //Checking if the list already has the letter in it
        if (find(list, letter) == nil){
            countDict[letter] = 1
            println("Letter not found, not appended")
        //If the letter is in the list, add its current value to 1
        }else{
            let number = Int(countDict[letter]!)
            countDict[letter] = number + 1
        }
    }
    return countDict
}

但由于某种原因,它不会在我的else语句中添加字母,只返回:

["r": 1, "o": 1, "p": 1, "s": 1, "t": 1]

我无法弄明白为什么。

如果有人能够理解为什么,或者对我的问题有更好的解决方案,我会非常感激。

3 个答案:

答案 0 :(得分:0)

NSCountedSet可以帮到你。实际上你可以只返回一个NSCountedSet并在最后跳过字典的创建。

func listCounter(usernames: [String])->Dictionary <String,Int> {

    let countedSet=NSCountedSet()

    for user in usernames{

        let index = user.substringToIndex(advance(user.startIndex,1))

        countedSet.addObject(index.lowercaseString)
    }

    var dict=Dictionary<String,Int>()

    let letters = countedSet.objectEnumerator().allObjects as [String]

    for letter in letters {
        dict[letter]=countedSet.countForObject(letter)
    }

    return dict
}

答案 1 :(得分:0)

您还可以使用map-reduce来生成输出

let thisList = ["Roman", "Serial", "Thomas", "Peter", "Pan", "Other", "Peter", "Remy"]

func firstLetterCountOfList(list: [String]) -> [String:Int] {

    let mappingFunction = {  (x: String) -> String in
            let index = advance(x.startIndex, 0)
            return String(x[index]).lowercaseString
    }

    let reducingFunction = { (x:[String:Int], y:String) -> [String:Int] in
        var output = x
        if let count = output[y] {
            output[y] = count + 1
        }
        else {
            output[y] = 1
        }

        return output
    }

    return list.map(mappingFunction).reduce([:], reducingFunction)
}

firstLetterCountOfList(thisList)

答案 2 :(得分:0)

您可以使用nil coalescing运算符进一步减少已使用reduce的已解决方案中的代码。 http://www.codingexplorer.com/nil-coalescing-swift/

successor函数获取元素的后继函数。如果元素为1则返回2.

let thisList = ["Roman", "Serial", "Thomas", "Peter", "Pan", "Other", "Peter", "Remy"]

func firstLetterCountOfList(list: [String]) -> [String:Int] {

    return list.reduce([:], { (var letterCount, name) -> [String:Int] in

        //Create the range to get first character.
        let range = advance(name.startIndex, 0)

        //Extract the first character here.
        let char = String(name[range]).lowercaseString

        /* This sets the character count to 1 if the char does
        not exist in the dictionary. ?? is nil coalescing operator.*/

        letterCount[char] = letterCount[char]?.successor() ?? 1 

        return letterCount
    })
}