计算列表中的名字的第一个字母
问题描述:
我试图创建一个函数,它将一个列表作为参数,并返回第一个字母的类型作为列表的名称,以及这些字母的数量,用于例如,如果我的名单看起来是这样的:计算列表中的名字的第一个字母
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
}
,但由于某种原因,在我的其他语句也不会加字母,只返回:
["r": 1, "o": 1, "p": 1, "s": 1, "t": 1]
,我想不通为什么。
如果任何人都能看到为什么,或者有更好的解决方案来解决我的问题,我会非常感激。
答
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
}
答
,你也可以利用地图,减少产生的输出
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)
答
您可以使用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
})
}
我不是一个很好的快速阅读器,但是不应该在if分支中将该字母添加到列表中吗? list似乎对我无条件保持为空 – danh 2015-01-21 00:20:29
yeah正如danh所说,list总是空的,并且从不附加到 – chris 2015-01-21 00:32:00
而不是'var list = [String](countDict.keys)'use dict'var firstCount = [String:Int]( )'来计数事件。 – 2015-01-21 00:34:03