func ramElment<X, T: CollectionType >(list: T) -> X {
let len = UInt32(list.count)
let element = arc4random_uniform(len)
return list[element]
}
它出现了:
错误:无法使用类型为“UInt32
)”的参数列表调用类型T.Index.Distance
的初始值设定项
let len = UInt32(list.count)
我检查过T.Index.Distance
是Int类型。但为什么我不能将类型更改为UInt32
?
谢谢!
答案 0 :(得分:3)
Index
的{{1}}是
CollectionType
:
ForwardIndexType
这意味着关联的类型public protocol ForwardIndexType : _Incrementable {
// ...
typealias Distance : _SignedIntegerType = Int
// ...
}
必须符合Distance
,并且(默认情况下)为_SignedIntegerType
,除非声明(或推断)
除此以外。
示例:以下是符合Int
的有效类型,
与ForwardIndexType
:
Distance == Int16
这是一个(用于演示目的,否则相当无用)
类型符合struct MyIndex : ForwardIndexType {
var value : Int16
func advancedBy(n: Int16) -> MyIndex {
return MyIndex(value: value + n)
}
func distanceTo(end: MyIndex) -> Int16 {
return end.value - value
}
func successor() -> MyIndex {
return MyIndex(value: value + 1)
}
}
func ==(lhs : MyIndex, rhs : MyIndex) -> Bool {
return lhs.value == rhs.value
}
CollectionType
,
Index == MyIndex
:
Index.Distance == Int16
示例:
struct MyCollectionType : CollectionType {
var startIndex : MyIndex { return MyIndex(value: 0) }
var endIndex : MyIndex { return MyIndex(value: 3) }
subscript(position : MyIndex) -> String {
return "I am element #\(position.value)"
}
}
但是我们也可以在不声明的情况下定义前向索引类型
任何let coll = MyCollectionType()
for elem in coll {
print(elem)
}
/*
I am element #0
I am element #1
I am element #2
*/
类型,并使用默认协议实现
对于Distance
和advancedBy()
:
distanceTo()
现在struct MyOtherIndex : ForwardIndexType {
var value : Int16
func successor() -> MyOtherIndex {
return MyOtherIndex(value: value + 1)
}
}
func ==(lhs : MyOtherIndex, rhs : MyOtherIndex) -> Bool {
return lhs.value == rhs.value
}
因为这是默认类型
如MyOtherIndex.Distance == Int
中所定义。
那么这对您的功能有何影响?
你无法想象
对于任意集合,ForwardIndexType
为Index.Distance
。
您可以将函数限制为集合类型
Int
:
Index.Distance == Int
但您也可以利用func randomElement<T: CollectionType where T.Index.Distance == Int>(list: T)
可以转换为_SignedIntegerType
:
IntMax
另请注意,返回类型确定为func randomElement<T: CollectionType>(list: T) -> T.Generator.Element {
let len = UInt32(list.count.toIntMax())
let element = IntMax(arc4random_uniform(len))
return list[list.startIndex.advancedBy(T.Index.Distance(element))]
}
,
并且不能是任意泛型类型T.Generator.Element
。
此功能适用于任意集合,例如X
,Array
或ArraySlice
:
String.CharacterView
还要使用上面的自定义集合类型:
let array = [1, 1, 2, 3, 5, 8, 13]
let elem1 = randomElement([1, 2, 3])
let slice = array[2 ... 3]
let elem2 = randomElement(slice)
let randomChar = randomElement("abc".characters)
答案 1 :(得分:2)
在问题的标题中,您谈到了Array
。但是在您的代码中,您将输入参数声明为CollectionType
。
如果你真的想收到一个通用数组参数,那么这就是代码
func randomElement<T>(list: [T]) -> T {
let len = UInt32(list.count)
let random = Int(arc4random_uniform(len))
return list[random]
}
答案 2 :(得分:0)
这是你想要的最简单的例子。
extension CollectionType where Index.Distance == Int {
func randomElement() -> Self.Generator.Element {
let randomIndex = Int(arc4random_uniform(UInt32(count)))
return self[startIndex.advancedBy(randomIndex)]
}
}