gpt4 book ai didi

swift - 通过泛型函数获取数组中的随机元素

转载 作者:搜寻专家 更新时间:2023-11-01 06:06:35 26 4
gpt4 key购买 nike

func ramElment<X, T: CollectionType >(list: T) -> X {
let len = UInt32(list.count)
let element = arc4random_uniform(len)
return list[element]
}

它弹出:

错误:无法使用类型为“(T.Index.Distance)”的参数列表调用类型 UInt32 的初始化程序

let len = UInt32(list.count)

我检查过 T.Index.Distance 是 Int 类型。但为什么我不能将类型更改为 UInt32

谢谢!

最佳答案

CollectionTypeIndex 是一个 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
}

这是一个(用于演示目的,否则非常无用)符合 CollectionTypeIndex == 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 类型,并使用默认协议(protocol)实现对于 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.DistanceInt 用于任意集合。

您可以限制使用集合类型的函数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

此函数适用于任意集合,例如 ArrayArraySliceString.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)

还有上面的自定义集合类型:

let mc = MyCollectionType()
let r = randomElement(mc)

关于swift - 通过泛型函数获取数组中的随机元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35551418/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com