Массив, в котором все элементы одного типа, делает элемент соответствующим некоторому протоколу

я составил протокол

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]

Икс -5 -4 -3 -2 -1 0 1 2 3 4 5 с [у] с[1] с [2] с[0] с [1] с [2] с[0] с [1] с [2] с[0] с [1] с [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
    }
}()

Формула применяется к массиву, даже если длина отличается.

Любой массив, в котором тип элемента массива одинаков, может быть преобразован в двунаправленную бесконечную последовательность путем зацикливания заданных значений.

Я не хочу писать расширения для каждого типа, который может быть включен в массив.

Как я могу выполнить требования? Или любой метод достижения той же цели приветствуется.

Тут как минимум два вопроса. Пожалуйста, разделите их!

Jessy 10.01.2023 21:08

Что T делает в вашем протоколе? Кажется, вы его нигде не используете. Действительно ли IndexConvertable связан с вашим вопросом? Вы, похоже, тоже не нуждаетесь и не используете его.

Rob Napier 10.01.2023 23:49
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
2
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете ограничить расширение на основе универсального типа, чтобы вы могли сделать что-то вроде этого

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"
Ответ принят как подходящий

У вас два несвязанных вопроса. Это ответ для второго:

Алгоритмы предложений зациклены. Если это не соответствует вашим потребностям,

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

Другие вопросы по теме