为什么这段代码有歧义?
Why is this code ambiguous?
我已将此扩展写入 SequenceType
以模仿 Python's collections.Counter
。
let input = [
"a", "a", "a", "a", "a",
"b", "b", "b", "b",
"c", "c", "c",
"d", "d",
"e"
]
let counts = input.countRepetitions()
print(counts) //expected result: ["a": 5 , "b" : 4, "c" : 3, "d" : 2, "e" : 1]
代码如下:
extension SequenceType where Self.Generator.Element : Hashable {
func countRepetitions() -> [Self.Generator.Element : Int] {
return self.reduce([Self.Generator.Element : Int]()) { dict, element in
dict[key: element] = (dict[element] ?? 0) + 1
}
}
}
我收到以下错误:
Playground execution failed: OS X.playground:26:22: error: type of expression is ambiguous without more context
return self.reduce([Self.Generator.Element : Int]()) { dict, element in
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这似乎是用嵌套定义变量时的限制
类型。虽然
let foo1: [Self.Generator.Element : Int] = [:]
在您的方法中编译,这不会:
let foo2 = [Self.Generator.Element : Int]()
// error: type of expression is ambiguous without more context
作为解决方法,您可以定义类型别名:
typealias E = Self.Generator.Element
let foo3 = [E : Int]()
适用于您的情况:
extension SequenceType where Self.Generator.Element : Hashable {
func countRepetitions() -> [Self.Generator.Element : Int] {
typealias E = Self.Generator.Element
return self.reduce([E : Int]()) { (dict, element) -> [E : Int] in
var dict = dict
dict[element] = (dict[element] ?? 0) + 1
return dict
}
}
}
(注意闭包参数是常量,所以你必须
首先是可变副本。另外闭包必须 return 一个值。)
但实际上你可以避免问题并让编译器推断类型:
extension SequenceType where Self.Generator.Element : Hashable {
func countRepetitions() -> [Self.Generator.Element : Int] {
return self.reduce([:]) { (dict, element) in
var dict = dict
dict[element] = (dict[element] ?? 0) + 1
return dict
}
}
}
另请注意,reduce
在每次迭代中都会创建一个新字典
步。
一个更有效的解决方案是
extension SequenceType where Generator.Element : Hashable {
func countRepetitions() -> [Generator.Element : Int] {
var dict: [Generator.Element: Int] = [:]
self.forEach {
dict[[=15=]] = (dict[[=15=]] ?? 0) + 1
}
return dict
}
}
我也省略了(多余的)Self.
。
我已将此扩展写入 SequenceType
以模仿 Python's collections.Counter
。
let input = [
"a", "a", "a", "a", "a",
"b", "b", "b", "b",
"c", "c", "c",
"d", "d",
"e"
]
let counts = input.countRepetitions()
print(counts) //expected result: ["a": 5 , "b" : 4, "c" : 3, "d" : 2, "e" : 1]
代码如下:
extension SequenceType where Self.Generator.Element : Hashable {
func countRepetitions() -> [Self.Generator.Element : Int] {
return self.reduce([Self.Generator.Element : Int]()) { dict, element in
dict[key: element] = (dict[element] ?? 0) + 1
}
}
}
我收到以下错误:
Playground execution failed: OS X.playground:26:22: error: type of expression is ambiguous without more context
return self.reduce([Self.Generator.Element : Int]()) { dict, element in
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这似乎是用嵌套定义变量时的限制 类型。虽然
let foo1: [Self.Generator.Element : Int] = [:]
在您的方法中编译,这不会:
let foo2 = [Self.Generator.Element : Int]()
// error: type of expression is ambiguous without more context
作为解决方法,您可以定义类型别名:
typealias E = Self.Generator.Element
let foo3 = [E : Int]()
适用于您的情况:
extension SequenceType where Self.Generator.Element : Hashable {
func countRepetitions() -> [Self.Generator.Element : Int] {
typealias E = Self.Generator.Element
return self.reduce([E : Int]()) { (dict, element) -> [E : Int] in
var dict = dict
dict[element] = (dict[element] ?? 0) + 1
return dict
}
}
}
(注意闭包参数是常量,所以你必须 首先是可变副本。另外闭包必须 return 一个值。)
但实际上你可以避免问题并让编译器推断类型:
extension SequenceType where Self.Generator.Element : Hashable {
func countRepetitions() -> [Self.Generator.Element : Int] {
return self.reduce([:]) { (dict, element) in
var dict = dict
dict[element] = (dict[element] ?? 0) + 1
return dict
}
}
}
另请注意,reduce
在每次迭代中都会创建一个新字典
步。
一个更有效的解决方案是
extension SequenceType where Generator.Element : Hashable {
func countRepetitions() -> [Generator.Element : Int] {
var dict: [Generator.Element: Int] = [:]
self.forEach {
dict[[=15=]] = (dict[[=15=]] ?? 0) + 1
}
return dict
}
}
我也省略了(多余的)Self.
。