2014-12-14 2 views
4

Я пытаюсь написать функцию, которая примет в качестве аргумента массив символов (назовите это слово) и один символ и вернет массив слов, с характером вставленной во всех положениях:Swift - вставить в массив символов, функциональное решение

Пример

typealias Word = [Character] 

func insert(letter: Character, into word: Word) -> [Word] { 
} 

Так телефону:

insert("c", into: ["a", "b"]) 

вернется:

[["c", "a", "b"], ["a", "c", "b"], ["a", "b", "c"]] 

Простейших я придумал до сих пор:

func insert(letter: Character, into word: Word) -> [Word] { 

    return Array<Int>(0...word.count).map() { 
     var newWord = word 
     newWord.insert(letter, atIndex: $0) 
     return newWord 
    } 
} 

, от которого я получил родовую версию:

extension Array 
{ 
    func insert(element: T) -> [[T]] { 

     return (0...self.count).map() { 
      var newArray = self 
      newArray.insert(element, atIndex: $0) 
      return newArray 
     } 
    } 
} 

Однако, это предполагает создание изменяемой копии входное слово. Это там лучший/более элегантный/более простой (функциональный) способ достичь этого?

ответ

2

Я переместила бы «не-мутирует вставки массива» в отдельный метод:

extension Array 
{ 
    func arrayByInserting(element: T, atIndex: Int) -> [T] { 
     var result = self 
     result.insert(element, atIndex: atIndex) 
     return result 
    } 

    func insert(element: T) -> [[T]] { 
     return (0 ... self.count).map() { self.arrayByInserting(element, atIndex: $0) } 
    } 
} 

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

Это может быть написано немного короче с использованием срезов:

func arrayByInserting(element: T, atIndex: Int) -> [T] { 
    return self[0 ..< atIndex] + [element] + self[atIndex ..< self.count] 
} 

Однако быстрый тест показал, что этот метод примерно в 10 раз медленнее чем ваш метод.

1

Вы можете найти очень интересные функциональные примеры в Swift здесь: objc.io Functional Snippets

В «перестановки» фрагменты кода является то, что вы ищете.

Здесь приведен упрощенный пример. Но я настоятельно рекомендую фрагменты objc.io.

Массив Extension:

extension Array { 
    var decompose : (head: T, tail: [T])? { 
     return (count > 0) ? (self[0], Array(self[1..<count])) : nil 
    } 
} 

А вот общая функция:

func between<T>(x: T, ys: [T]) -> [[T]] { 
if let (head, tail) = ys.decompose { 
    return [[x] + ys] + between(x, tail).map { [head] + $0 } 
} else { 
    return [[x]] 
} 
} 

Это должно решить вашу проблему:

let char: Character = "c" 
let charArray = ["a", "b"] as [Character] 
let r = between(char, charArray) 
+1

хорошее решение (но очень медленно: около 1000 раз медленнее, чем метод в вопросе - просто заявляя). –

+1

Yep ... печально: -/ Но вопрос, похоже, требует подхода _functional_. Насколько готов компилятор Swift и оптимизатор для функционального программирования, остается открытым для меня вопросом. И, наверное, немного не по теме. –

Смежные вопросы