2014-11-08 30 views
5

Option s ürününü List ürününe eklemek için en iyi yol nedir?Listeleme Seçenekleri ekleme

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

Con: Burada

benim ilk denemede oluşturduğu 2 tmp List

(I .toList (biliyorum) [A] iterable için Seçenek bir örtük dönüştürme olduğundan isteğe bağlıdır [A])

başka deneyin ortalama

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) 

Daha iyi f ama daha az okunabilir…

Başka bir yolu var mı? Eklemek birçok seçenek, binlerce daha yakın, ben daha az sayıda düşünmek varsa

+1

Neden List [A] olarak Birini [A] eklemek istiyoruz. Tabii ki eklemeye değer bir şey olup olmadığını görmek ister misin? –

+1

Listenin sonuna eklemeyin. – ziggystar

+2

Evet, Stack Overflow'ta o adam olmaktan nefret ediyorum, ama eğer sonuna kadar eklediğinizi buluyorsanız, şu soruyu sormaya değer: “List” 'ü kullanmanın bir nedeni var mı?)? –

cevap

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

Veya, kısacası için: '(s /: os) ((l, o) => o.fold (l) (l: + _))' –

+0

@BenReich teşekkürler, ben bu fikri koydum. Bir büyüye benzeyebilir. –

1

Orijinal çözüm iyi olmalı Bu performans artışı verebilir değişken List Builder

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

kullanabilirsiniz

-2
  1. Option[A], List[A]'a ekleyemezsiniz. List[Option[A]]'u kullanmanız ve daha sonra bir seçenek eklemek oldukça önemsiz veya her seçenek için gerçekten bir şey tutup tutmadığını (Some(a: A)) kontrol etmeli ve sadece listeye eklemelisiniz.
  2. Listedeki öğelerin sırası, en azından ekleme aşamasında değil, çok önemli değilse, :: işlecini kullanarak, en baştan sonuna en sonunda eklemek en iyisi olacaktır. Bir listenin başlangıcına öğeler eklemek sabit zaman alır. Sonunda onları eklemek, O (n)'u alır; burada n, listede bulunan öğelerin sayısıdır. Bunun nedeni, programın ilk önce tüm listeyi başlangıçtan sonuna kadar geçirmesi ve yalnızca yeni öğeyi ekleyebilmesidir.

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

    veya sonra

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

    Ve

    , sizin gibi tüm unsurları ekledikten sonra, sadece onlara sahip olmak ls.reverse arayabilirsiniz: Ya

Yani, sorunun cevabı olacak Onları ekliyor olsaydınız sırayla olurdu.

+0

Evet, 'Seçenek [A]' seçeneğini '[A]' listesine ekleyebilirsiniz. Sadece bir REPL'yi tetikleyin ve şu kodu yapıştırın: 'List (1,2,3) ++ None ++ Bazı (4) ++ Bazı (5) ++ Hiçbiri' Bu, tam olarak ikinci çözümünüzle aynı şekilde çalışır ancak çok daha güzel. Ayrıca, 'ls.reverse' işlevinin çağrılması da amaçlanan orijinal listenizi de tersine çevirecektir. –

+0

Bu hatayı düzeltmek için 'case None => ls' ile gönderdiğiniz için teşekkür ederiz. Fakat. 1. Yazar, içerik hakkında hiçbir şey söylemedi. Bu yüzden ilk önce "sipariş önemli değilse" yazdım, çünkü belki de değil ve daha hızlı olan '' 'kullanabiliriz. Bunun yanında, '++' ile listelenecek bir seçenek ekledikçe, gerçekten bir ** seçeneği de eklemiyor **. Bu, bir ** ya da hiçbir şey eklemez :) – makingthematrix

+0

1. Bir 'List ', tanım gereği için sipariş verilir, bu yüzden siparişi dağıtan bir çözüm sağlamak kitabımda yanlıştır. 2. Soru, yazarın “bir listeye bir seçenek eklemenin” ne anlama geldiğine dair iki örnek vermiş ve bunları denemiş olsaydınız gerçekten de “A ya da hiçbir şey eklemediklerini” görebilirsiniz. –