提问人:Harry CHOI 提问时间:1/11/2023 更新时间:1/30/2023 访问量:74
一个数组,其中所有元素都是相同的类型,使元素符合某种协议
An array where all the element are the same type, make the element conforms to some protocol
问:
我做了一个协议
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
}
}()
即使长度不同,该公式也适用于数组。
数组元素类型相同的任何数组都可以通过循环给定值转换为双向无穷序列。
我不想为数组中可以包含的每个类型编写扩展。
我怎样才能满足这些要求?或任何实现相同目标的方法都受到欢迎。
答:
-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
评论
T