gpt4 book ai didi

swift - Swift 中的泛型

转载 作者:搜寻专家 更新时间:2023-10-31 22:42:08 24 4
gpt4 key购买 nike

我正在学习 Swift 中的泛型。对我来说,这个话题很难理解。在我正在阅读的书中,泛型有 2 个挑战:

第一个挑战:它要求编写一个函数findAll(_:_:),该函数采用符合 Equatable 协议(protocol)的任何类型 T 的数组和单个元素(也是 T 类型)。 findAll(_:_:) 应该返回一个整数数组,对应于数组中找到元素的每个位置。例如,findAll([5,3,7,3,9], 3] 应该返回 [1,3]

第二个挑战:修改 findAll(_:_:) 以接受 Collection 而不是数组,它会提示“您需要更改返回值从 [Int] 类型到 Collection 协议(protocol)关联类型的数组”

这是我为第一个挑战所做的

func findAll<T:Equatable> (_ first: [T], _ second: T) -> [Int] {
var array = [Int]()

for i in 0..<first.count {
if first[i] == second {
array.append(i)
}
}
return array
}

对于第二个挑战,我正在考虑的是一个可以传递集合(可以是数组、字典或集合)的通用函数。但是对于 Set 类型,由于它没有定义的顺序,您如何找到一个项目在 Set 中的位置?

谢谢。

最佳答案

集合的下标方法定义为

public subscript(position: Self.Index) -> Self.Iterator.Element { get }

这意味着你的函数应该接受参数

  • 集合C,和
  • 关联类型 C.Iterator.Element 的值

并返回一个C.Index数组。此外,元素类型应该是Equatable:

func findAll<C: Collection> (_ collection: C, _ element: C.Iterator.Element) -> [C.Index]
where C.Iterator.Element: Equatable
{ ... }

与您的数组解决方案类似,可以循环遍历集合的索引:

func findAll<C: Collection> (_ collection: C, _ element: C.Iterator.Element) -> [C.Index]
where C.Iterator.Element: Equatable
{
var result: [C.Index] = []

var idx = collection.startIndex
while idx != collection.endIndex {
if collection[idx] == element {
result.append(idx)
}
collection.formIndex(after: &idx)
}

return result
}

人们会期望像这样的东西

for idx in collection.startIndex ..< collection.endIndex
// or
for idx in collection.indices

有效,但是(在 Swift 3 中)这需要一个额外的约束在关联的 Indices 类型上:

func findAll<C: Collection> (_ collection: C, _ element: C.Iterator.Element) -> [C.Index]
where C.Iterator.Element: Equatable, C.Indices.Iterator.Element == C.Index
{

var result: [C.Index] = []

for idx in collection.indices {
if collection[idx] == element {
result.append(idx)
}
}

return result
}

这在 Swift 4 中不再需要,参见示例 Unable to use indices.contains() in a Collection extension in Swift 3一个很好的解释。

这现在可以使用 filter 来简化:

func findAll<C: Collection> (_ collection: C, _ element: C.Iterator.Element) -> [C.Index]
where C.Iterator.Element: Equatable, C.Indices.Iterator.Element == C.Index
{
return collection.indices.filter { collection[$0] == element }
}

示例(Character 的集合):

let chars = "abcdabcdabcd".characters
let indices = findAll(chars, "c")
for idx in indices {
print(chars[idx])
}

Set 也是一个 Collection,它有一个关联的 Indextype 和一个 subscript 方法。示例:

let set = Set([1, 2, 3, 4, 5, 6, 7, 8, 9])
let indices = findAll(set, 3)
for idx in indices {
print(set[idx])
}

最后,您可能希望将函数定义为方法Collection 类型上:

extension Collection where Iterator.Element: Equatable, Indices.Iterator.Element == Index {
func allIndices(of element: Iterator.Element) -> [Index] {
return indices.filter { self[$0] == element }
}
}

// Example:
let indices = [1, 2, 3, 1, 2, 3].allIndices(of: 3)

关于swift - Swift 中的泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44449839/

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