Как преобразовать массив в кортеж?

Я просто хочу преобразовать массив в кортеж в Swift; что-то вроде следующего:

>>> myArray = [1,2,3,4,5]
>>> mytuple = tuple(myArray)
>>> mytuple
(1, 2, 3, 4, 5)

Какой самый простой способ сделать это?

(Я только начал изучать Swift сегодня, поэтому я очень, очень новый).

Ответы

Ответ 1

Вы не можете этого сделать, потому что размер кортежа является частью его типа, и это не так для массива. Если вы знаете длину массива, вы можете просто сделать let myTuple = (myArray[0], myArray[1], ...). Или вы можете построить свою архитектуру вокруг кортежей с самого начала. Что вы пытаетесь сделать?

Это обычная проблема, которая возникает во многих других языках. См. Как преобразовать список в кортеж в Haskell?

Ответ 2

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

typealias TupleType = (UInt8, UInt8, UInt8)

var array = [2, 3, 4] as [UInt8]
var tuple = UnsafeMutablePointer<StepsType>(malloc(UInt(sizeof(TupleType))))
memcpy(tuple, array, UInt(array.count))

Больше всего этого можно найти здесь: https://codereview.stackexchange.com/questions/84476/array-to-tuple-in-swift/84528#84528


Потому что 70% из нас - очень визуальные существа:

enter image description here

Ответ 3

Боишься небезопасных указателей? Или нужна поддержка кортежей с разными типами внутри?

Это также можно сделать так:

public extension Array {

    public var tuple: Any? {
        switch count {
        case 0:
            return ()
        case 1:
            return (self[0])
        case 2:
            return (self[0], self[1])
        case 3:
            return (self[0], self[1], self[2])
        case 4:
            return (self[0], self[1], self[2], self[3])
        case 5:
            return (self[0], self[1], self[2], self[3], self[4])
        default:
            return nil
     }
 }

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

Я использовал этот подход в ArrayPlusTuple.

Поэтому вместо того, чтобы писать эту функцию самостоятельно, вы можете просто добавить pod 'ArrayPlusTuple' в файл модуля и получить эту проверенную функцию бесплатно.

Ответ 4

Если вы хотите извлечь несколько значений из массива одновременно, возможно, следующий код может помочь вам

extension Array {
    func splat() -> (Element,Element) {
        return (self[0],self[1])
    }

    func splat() -> (Element,Element,Element) {
        return (self[0],self[1],self[2])
    }

    func splat() -> (Element,Element,Element,Element) {
        return (self[0],self[1],self[2],self[3])
    }

    func splat() -> (Element,Element,Element,Element,Element) {
        return (self[0],self[1],self[2],self[3],self[4])
    }
}

тогда вы можете использовать это так

  let (first,_,third) = ( 0..<20 ).map { $0 }.splat()

Вы даже можете написать codegen для генерации кода расширения

Ответ 5

Это мое универсальное решение для копирования данных массива в кортеж. Единственная проблема, которую я не смог решить, это проверить тип элемента в кортеже и элемент из массива.

/// Unsafe copy array to tuple
func unsafeCopyToTuple<ElementType, Tuple>(array: inout Array<ElementType>, to tuple: inout Tuple) {
    withUnsafeMutablePointer(to: &tuple) { pointer in
        let bound = pointer.withMemoryRebound(to: ElementType.self, capacity: array.count) { $0 }
        array.enumerated().forEach { (bound + $0.offset).pointee = $0.element }
    }
}