一个数组,其中所有元素都是相同的类型,使元素符合某种协议

An array where all the element are the same type, make the element conforms to some protocol

提问人:Harry CHOI 提问时间:1/11/2023 更新时间:1/30/2023 访问量:74

问:

我做了一个协议

protocol IndexConvertable{
    associatedtype T
    static func convertAnyTypeToInt(_ type: Self) -> Int
    static func convertIntToAnyType(_ int: Int) -> Self
}

该协议允许我索引具有无限双向值的类型,例如。日期

例如。

extension Date: IndexConvertable{
    typealias T = Date
    
    static func convertAnyTypeToInt(_ date: Date) -> Int {
         date.convertDateToInt()
    }
    
    static func convertIntToAnyType(_ int: Int) -> Date {
         int.convertIntToDate()
    }
}

extension Date{
    /// This function converts a Date to an Int.
    func convertDateToInt(){
        ...
    }
}

extension Int{
    /// This function converts an Int to a Date.
    func convertIntToDate{
        ...
    }
}

从逻辑上讲,数组元素类型相同的任何数组都可以通过循环给定值转换为双向无限序列。

示例 1:

let colors: [Color] = [.red, .blue, .purple]

goal => [... .red, .blue, .purple, .red, .blue, .purple ...]

示例 2:

struct ColorView: View{
    let color: Color
    var body: some View{
        color.ignoreSafeArea()
    }
}

let colorViews: [ColorView] = [
    ColorView(color: .red),
    ColorView(color: .blue),
    ColorView(color: .purple)
]

=> [... ColorView(color: .red), ColorView(color: .blue), ColorView(color: .purple), ColorView(color: .red), ColorView(color: .blue), ColorView(color: .purple) ...]

换算计算:

let c: [Color] = [.red, .blue, .purple]

x -5 -4 -3 -2 -1 0 1 2 3 4 5
c[y] c[1] c[2] c[0] c[1] c[2] c[0] c[1] c[2] c[0] c[1] c[2]
。蓝 。紫色 。红 。蓝 。紫色 。红 。蓝 。紫色 。红 。蓝 。紫色
let count = c.count

//Formula
y = { //if x is positive
    if x >= 0{
        x % count
    }else{ //if x is negative
        ((x % count) + count) % count
    }
}()

即使长度不同,该公式也适用于数组。

数组元素类型相同的任何数组都可以通过循环给定值转换为双向无穷序列。

我不想为数组中可以包含的每个类型编写扩展。

我怎样才能满足这些要求?或任何实现相同目标的方法都受到欢迎。

数组 swift swiftui 序列

评论

0赞 1/11/2023
这里至少有两个问题。请把它们分开!
1赞 Rob Napier 1/11/2023
您的协议中正在做什么?你似乎没有在任何地方使用它。IndexConvertable 真的与您的问题有关吗?您似乎也不需要或使用它。T

答:

-1赞 user20977963 1/11/2023 #1

您可以基于泛型类型约束扩展,因此您可以执行如下操作

extension Collection where Index == Int {
    public subscript(index: Int, circular isCircular: Bool) -> Element {
        if !isCircular {
            return self[index]
        }
        
        let remainder = index % count
        let validIndex = remainder < Index.zero ? count + remainder : remainder
        return self[validIndex]
    }
}

使用示例

let numbers = [1, 2, 3, 4, 5]
numbers[-1, circular: true] // 5
numbers[6, circular: true] // 2
numbers[6] // out of bounds

let letters = ["a", "b", "c"]
letters[3, circular: true] // "a"
1赞 user652038 1/11/2023 #2

您有两个不相关的问题。这是第二个问题的答案:

算法提供循环。如果这不符合您的需求,

public extension Collection {
  /// Circularly wraps `index`, to always provide an element,
  /// even when `index` is not valid.
  subscript(cycling index: Index) -> Element {
    self[cycledIndex(index)]
  }

  /// Circularly wraps the result, to always provide an element.
  func cycledIndex(_ index: Index, offsetBy distance: Int = 0) -> Index {
    self.index(
      startIndex,
      offsetBy:
        (self.distance(from: startIndex, to: index) + distance)
        .modulo(count)
    )
  }
public extension BinaryInteger {
  func modulo(_ divisor: Self) -> Self {
    (self % divisor + divisor) % divisor
  }
}
[0, 1][modulo: -1] // 1
[0, 1][modulo: 2] // 0