2014-11-08 21 views
5

Was ist der beste Weg, Option s zu List hinzuzufügen.So fügen Sie einer Liste Optionen hinzu

Hier ist mein erster Versuch:

def append[A](as: List[A], maybeA1 : Option[A], maybeA2: Option[A]) : List[A] = as ++ maybeA1.toList ++ maybeA2.toList 

Con: Es schafft 2 tmp List

(ich weiß .ToList() ist optional, da es eine implizite Konvertierung von Option ist [A] zu Iterable [A])

Ein anderer Versuch ist

def append2[A](ls: List[A], maybeA : Option[A]) : List[A] = maybeA.map(_ :: ls).getOrElse(ls) 
def append[A](as: List[A], maybeA1 : Option[A], maybeA2: Option[A]) : List[A] = append2(append2(as, maybeA1), maybeA2) 

Besser pro f aber weniger lesbar ...

Gibt es einen anderen Weg?

+1

Warum möchten Sie eine Option [A] zu einer Liste [A] hinzufügen. Wollen Sie sicher sehen, ob etwas hinzuzufügen ist? –

+1

Nicht am Ende einer Liste hinzufügen. – ziggystar

+2

Ja, ich hasse es, auf Stack Overflow zu sein, aber wenn du dich am Ende anhängst, ist es eine Frage wert: Gibt es tatsächlich einen Grund, warum du 'List' hier verwendest (anstatt einer anderen Art von Sequenz)) –

Antwort

5
def combine[A](s: Seq[A], o: Option[A]) = (s /: o)(_ :+ _) 
def combineAll[A](s: Seq[A], os: Option[A]*) = (s /: os)(combine) 

combineAll(List(1), Some(2), None, Some(3)) 
//res0: Seq[Int] = List(1, 2, 3) 
+2

Oder kurz gesagt: '(s /: os) ((l, o) => o.fach (l) (l: + _))' –

+0

@BenReich danke, ich habe die idee darin eingefügt. Es mag wie ein magisches tho aussehen –

1

können Sie wandelbar verwenden Liste Builder

val builder = scala.collection.mutable.ListBuffer.empty[A] 
builder ++= list 
builder ++= maybe1 
builder ++= maybe2 
... 
builder.result() 

Es kann Leistungsverbesserungen geben, wenn Sie eine Menge von Optionen zum Hinzufügen, näher an Tausende, ich denke, auf kleinere Anzahl ursprüngliche Lösung sollte

-2
gut
  1. Sie können Option[A] nicht zu List[A] hinzufügen. Sie müssen entweder List[Option[A]] verwenden und dann ist das Hinzufügen einer Option ziemlich trivial, oder Sie müssen für jede Option prüfen, ob es tatsächlich etwas enthält (Some(a: A)) und es dann nur dann zur Liste hinzufügen.
  2. Wenn die Reihenfolge der Elemente in der Liste nicht sehr wichtig ist, zumindest nicht während der Addierphase, dann wäre es am besten, sie am Anfang anstelle des Endes mit dem Operator :: hinzuzufügen. Das Hinzufügen von Elementen zum Anfang einer Liste benötigt konstante Zeit. Hinzufügen sie am Ende dauert O (n) wo n ist die Anzahl der Elemente bereits in der Liste. Das liegt daran, dass das Programm zuerst die gesamte Liste vom Anfang bis zum Ende durchlaufen muss und erst dann das neue Element hinzufügen kann.

So wird die Antwort auf Ihre Frage entweder:

def add[A](ls: List[Option[A]], maybeA : Option[A]) = maybeA :: ls 

oder

def add[A](ls: List[A], maybeA : Option[A]) = maybeA match { 
    case Some(a) => a :: ls 
    case None => ls 
} 

Und dann, nachdem alle Elemente hinzufügen, die Sie mögen, können Sie nur ls.reverse nennen, sie zu haben in der Reihenfolge, die du haben würdest, wenn du sie anhängest.

+0

Ja, Sie können 'Option [A]' zu 'List [A]' hinzufügen. Starten Sie einfach eine REPL und fügen Sie diesen Code ein: 'List (1,2,3) ++ None ++ Some (4) ++ Some (5) ++ None' Dies funktioniert genauso wie Ihre zweite Lösung, aber ist viel schöner. Wenn Sie 'ls.reverse' aufrufen, wird auch Ihre ursprüngliche Liste umgekehrt, was nicht beabsichtigt ist. –

+0

Danke für die Korrektur dieses Fehlers mit 'case None => ls'. Aber. 1. Der Autor hat nichts über den Kontext gesagt. Deshalb schrieb ich zuerst "wenn die Reihenfolge nicht wichtig ist", weil es vielleicht nicht so ist und wir '' 'verwenden können, was schneller ist. Nebenbei, das Hinzufügen einer Option zum Auflisten mit '++' ... nun, es fügt nicht wirklich eine ** Option ** hinzu. Es fügt ** A ** oder nichts hinzu :) – makingthematrix

+0

1. Eine "Liste" per Definition ist bestellt, so dass eine Lösung, die die Reihenfolge versagt, ist in meinem Buch, falsch. 2. Die Frage lieferte zwei Beispiele dafür, was der Autor mit "Hinzufügen einer Option zu einer Liste" meinte, und wenn Sie sie ausprobiert hätten, könnten Sie sehen, dass sie tatsächlich "add A or nothing" sind. –

Verwandte Themen