Ios 使用泛型将两个泛型数组放入一个Swift字典
我试图将两种不同的泛型类型放入一个集合中。在本例中,有两个数组,一个包含Ios 使用泛型将两个泛型数组放入一个Swift字典,ios,swift,macos,Ios,Swift,Macos,我试图将两种不同的泛型类型放入一个集合中。在本例中,有两个数组,一个包含Ints,另一个包含Strings let intArray = Array<Int>() let stringArray = Array<String>() let dict = [1:intArray, "one": stringArray] 这导致了两个错误 不支持将“Hashable”用作符合协议“Hashable”的具体类型。 协议“Hashable”只能用作一般约束,因为它具有自身或关
Int
s,另一个包含String
s
let intArray = Array<Int>()
let stringArray = Array<String>()
let dict = [1:intArray, "one": stringArray]
这导致了两个错误
- 不支持将“Hashable”用作符合协议“Hashable”的具体类型。
- 协议“Hashable”只能用作一般约束,因为它具有自身或关联的类型要求
import Foundation
并使用NSDictionary
作为类型工作正常
let dict: NSDictionary = [1:intArray, "one": stringArray]
但是,在不使用基础的情况下,这也应该是在纯SWIFT中的。词典
的类型是什么
编辑:这显然和键的类型有更多的关系。它们必须是相同的类型,而不仅仅符合Hashable
let dict: [Int:Any] = [1:intArray, 2: stringArray]
这很有效。但有可能使值的类型更精确吗<代码>[Int:Array]不起作用
字典的类型是什么
你可以尝试:
let dict: [NSObject: Any] = [1: intArray, "one": stringArray]
语句
let dict:[Hashable:Any]=…
未编译,因为字典的键类型必须是符合Hashable
的具体类型,例如Int
,String
等。Hashable
不是具体类型
上述建议有效,因为1NSObject
是一种具体类型(您可以从中实例化对象),2NSObject
是一个可散列的3。因为NSObjects
的子类的实例在这里也可以工作,4。编译器可以从字符串和数字文本初始化NSObject
子类
如果您不喜欢NSObject
作为键的类型,您可以创建自己的类或结构。请注意,您的第一次尝试让dict=[1:intArray,“one”:stringArray]
在包含Foundation
的情况下有效;生成一个NSDictionary
(因此无需显式声明此类型)
<> p>为什么在使用<代码>基金会<代码>时,可以使用这些类型的、显然的、通用的字典,是编译器在将快速的本地类型桥接到基础时执行的(在引擎盖后面)的隐式类型转换。
let intArray : [Int] = [10, 20, 30]
let stringArray : [String] = ["foo", "baz", "bar"]
let dict = [1:intArray, "onx": stringArray]
print(dict.dynamicType)
for e in dict {
print(e.dynamicType, e.key.dynamicType, e.value.dynamicType)
}
/* __NSDictionaryI
(AnyObject, AnyObject) __NSCFString _SwiftDeferredNSArray
(AnyObject, AnyObject) __NSCFNumber _SwiftDeferredNSArray */
上面的dict
中的键和值被包装在类型AnyObject
中;只能保存引用(类)类型的对象;值类型<代码> int <代码> >代码>字符串< /代码>为基础引用类型<代码>这仍然是一本NSDictionary
;e、 g.AnyObject
本身不符合Hashable
,因此它不能用作本机Swift字典中的键
如果您希望创建Swift本机“通用密钥”词典,我建议您创建一个符合Hashable
的包装器(比如一个结构),并包装底层(各种)密钥类型。参见例如(有点过时的)螺纹
详细介绍了@RobNapier的方法,这里有一种类似的方法,它使用enum
来处理字典的键和值:
enum Key: Equatable, Hashable {
case IntKey(Int)
case StringKey(String)
var hashValue: Int {
switch self {
case .IntKey(let value) : return 0.hashValue ^ value.hashValue
case .StringKey(let value) : return 1.hashValue ^ value.hashValue
}
}
init(_ value: Int) { self = .IntKey(value) }
init(_ value: String) { self = .StringKey(value) }
}
func == (lhs: Key, rhs: Key) -> Bool {
switch (lhs, rhs) {
case (.IntKey(let lhsValue), .IntKey(let rhsValue)) : return lhsValue == rhsValue
case (.StringKey(let lhsValue), .StringKey(let rhsValue)) : return lhsValue == rhsValue
default: return false
}
}
enum Value {
case IntValue(Int)
case StringValue(String)
init(_ value: Int) { self = .IntValue(value) }
init(_ value: String) { self = .StringValue(value) }
}
var dict = [Key: Value]()
dict[Key(1)] = Value("One")
dict[Key(2)] = Value(2)
dict[Key("Three")] = Value("Three")
dict[Key("Four")] = Value(4)
其根本原因是Hashable符合Equatable,Equatable具有==(lhs:Self,rhs:Self)
要求,这就是“协议'Hashable'只能用作通用约束,因为它具有自身或关联的类型要求”。此外,您需要=
来解决哈希冲突,因此,这似乎是编译器的合理抱怨。@AntonBronnikov的可能重复相关(但可能重复)链接线程包括字典中具有相同类型键的泛型值,而这包括值和键,后者(泛型键)是更复杂的部分。然而,我意识到这个threas可能是@dfri的复制品,对不起,你是对的。OP的问题更为广泛。在我的问题中已经提到了使用基础和NS字典。@ OrkoDon主要解释了为什么<代码> NSCORGNOR/<代码>在“快速”本机类型上似乎“一般性”地工作,当它实际上在引擎盖后面执行对引用类型的隐式类型转换时;我的答案的最后一部分(参考)指向了一个现有的线程,用于使用Swift:s nativeDictionary
type解决这个问题。安东尼科夫:不过,他的解决方案巧妙地解决了这个问题,很高兴他能帮助你!
enum Key: Equatable, Hashable {
case IntKey(Int)
case StringKey(String)
var hashValue: Int {
switch self {
case .IntKey(let value) : return 0.hashValue ^ value.hashValue
case .StringKey(let value) : return 1.hashValue ^ value.hashValue
}
}
init(_ value: Int) { self = .IntKey(value) }
init(_ value: String) { self = .StringKey(value) }
}
func == (lhs: Key, rhs: Key) -> Bool {
switch (lhs, rhs) {
case (.IntKey(let lhsValue), .IntKey(let rhsValue)) : return lhsValue == rhsValue
case (.StringKey(let lhsValue), .StringKey(let rhsValue)) : return lhsValue == rhsValue
default: return false
}
}
enum Value {
case IntValue(Int)
case StringValue(String)
init(_ value: Int) { self = .IntValue(value) }
init(_ value: String) { self = .StringValue(value) }
}
var dict = [Key: Value]()
dict[Key(1)] = Value("One")
dict[Key(2)] = Value(2)
dict[Key("Three")] = Value("Three")
dict[Key("Four")] = Value(4)