Свифт 2 Самоанализ

Я конвертирую какой-то «старый» код Swift в Swift 2.0 и сталкиваюсь с ошибкой, от которой не могу избавиться.
Моя функция получает массив типа (любого) и возвращает новый массив того же типа.

Этот код больше не работает в Swift 2.0:

func makePattern1<T>(var list: Array<T>) -> Array<T> {
    let theType = list.dynamicType
    var result = theType()
    for i in 1..<list.count {
        result.append(list[i])
        result.append(list[i-1])
    }
    return result
}

выдает сообщение об ошибке: «Инициализация из значения метатипа должна явно ссылаться на 'init'».

Исправление кода с помощью: var result = theType.init() дает ошибку «Тип выражения неоднозначен без дополнительного контекста».

> Что я упускаю?


person popisar    schedule 08.12.2015    source источник
comment
Есть ли у вас причина сделать это? Похоже, что то, что вы хотите, может быть достигнуто намного проще с map.   -  person Code Different    schedule 08.12.2015
comment
Кроме того, что мешает вам просто сказать var result = Array<T>()?   -  person 0x416e746f6e    schedule 08.12.2015
comment
var result = Array<T>() отлично работает, спасибо.   -  person popisar    schedule 08.12.2015
comment
Не могли бы вы привести пример с map?   -  person popisar    schedule 08.12.2015


Ответы (2)


Этот код написан на Swift 2.1 и использует функцию map, как вы просили в комментариях.

func makePattern1<T>(list: [T]) -> [T] {
    return list[0..<list.count-1]
        .enumerate()
        .map { [list[$0.index+1], list[$0.index]] }
        .flatten()
        .map { $0 as T }
}

Обновление №1

(спасибо, Мартин Р.)

func makePattern1<T>(list: [T]) -> [T] {
    return list[0..<list.count-1]
        .enumerate()
        .flatMap { [list[$0.index+1], list[$0.index]] }
}

Обновление №2

func makePattern1<T>(list: [T]) -> [T] {
    return [Int](1..<list.count).flatMap { [list[$0], list[$0-1]] }
}

Тест

makePattern1([1,2,3,4,5]) // > [2, 1, 3, 2, 4, 3, 5, 4]
person Luca Angeletti    schedule 08.12.2015
comment
.map + flatten можно объединить в flatMap, а потом можно еще убрать окончательный искусственный .map { $0 as T } - person Martin R; 08.12.2015

Просто для удовольствия: альтернативное решение:

func makePattern2<T>(list: [T]) -> [T] {
     return zip(list.dropFirst(), list).flatMap { [$0, $1] }
}

let m = makePattern2([1,2,3,4,5])
print(m) // [2, 1, 3, 2, 4, 3, 5, 4]

Примечания:

  • list.dropFirst() — это последовательность всех элементов массива, кроме первых.
  • zip(list.dropFirst(), list) — это последовательность из 4_ кортежей.
  • flatMap { [$0, $1] } снова объединяет эти кортежи в один массив.
person Martin R    schedule 08.12.2015
comment
Очень хорошо. Закрытие этого flatMap использует только параметры самого закрытия. Это чисто функциональное решение. - person Luca Angeletti; 08.12.2015