2015-09-30 12 views
8

Als Übung versuche ich Karte, Länge und Filter als eine Reduzierungsfunktion zu schreiben.Swift Karte schreiben, Länge, Filter als reduzieren

func map<T>(array: [T], f: (T->T)) -> [T] { 
    return array.reduce([]) { 
     (var seed, value) in 
     seed.append(f(value)) 
     return seed 
    } 
} 

func length<T>(array: [T]) -> Int { 
    return array.reduce(0){ (x,_) in x + 1 } 
} 

func filter<T>(array: [T], predicate: (T->Bool)) -> [T]{ 
    return array.reduce([]){ 
     (var seed, value) in 
     if predicate(value){ 
      seed.append(value) 
     } 
     return seed 
    } 
} 

Ist dies die eleganteste Syntax, die ich verwenden kann, um diese Funktionen als reduzieren zu schreiben? 2. Frage: Karte nimmt eine Funktion f: (T-> T) Grundsätzlich sagt der Typ, ich kann nur etwas vom Typ T, aber was, wenn die Funktion, die ich schreibe transformiert Typ T zu einem Bool, oder Int ... Wie erreiche ich das? Scheint Karte nicht

Antwort

6

Für eine Abbildung, die einen Typ T in eine (möglicherweise unterschiedliche) transformiert existiert Typ S einfach zwei Typ Platzhalter:

func map<T, S>(array: [T], f: (T->S)) -> [S] { 
    return array.reduce([]) { 
     (var seed, value) in 
     seed.append(f(value)) 
     return seed 
    } 
} 

Beispiel:

let x = map([1, 2, 3], f: { String($0) }) 
print(x) // ["1", "2", "3"] 

Ob dies "ist dies die eleganteste Syntax" ist auch eine Angelegenheit der persönlichen Meinung. Wenn Sie die append() Methode von Array Verkettung mit + ersetzen dann die seed Parameter benötigen nicht variabel sein:

func map<T, S>(array: [T], f: (T->S)) -> [S] { 
    return array.reduce([]) { 
     (seed, value) in 
     seed + [f(value)] 
    } 
} 

die mit Stenografie Parameternamen als

func map<T, S>(array: [T], f: (T->S)) -> [S] { 
    return array.reduce([]) { $0 + [ f($1) ] } 
} 

ähnlich geschrieben werden kann:

func filter<T>(array: [T], predicate: (T->Bool)) -> [T]{ 
    return array.reduce([]) { predicate($1) ? $0 + [ $1 ] : $0 } 
} 

Beachten Sie, dass eine Implementierung von map() und filter() mit reduce() (anstelle einer Schleife) ist ziemlich ineffektiv, weil ein neues Array in jedem Reduktionsschritt erstellt wird. Siehe zum Beispiel

für eine Analyse. Für eine Übung (wie Sie sagten) ist es in Ordnung, nur nicht so etwas in der Produktion verwenden).

+0

Muchas gracias, danke! Genau die Art von Feedback, nach der ich gesucht habe. Swift ist eine seltsame Landschaft am Anfang;) – Seneca

+0

Seltsame Landschaft, die dich dazu inspiriert hat, dies zu versuchen!?! :) – Grimxn

+0

Anscheinend gibt es so etwas wie Wandler;) Ausgezeichnete Möglichkeit, etwas Grundwissen über swift zu erwerben. – Seneca

0

Erweiterung Collection

extension CollectionType { 
func MyMap<T>(transform: (Self.Generator.Element) -> T) -> [T] { 
    let list = self.reduce([T]()) { (var seed, value) in 
     seed.append(transform(value)) 
     return seed 
    } 
    return list 
}} 

dann mit [1,2,3] .MyMap ({$ 0 + 1})