2009-05-21 16 views
6

Harita işlevinin bir listenin (bir sıra) her öğesini aldığını ve ona bir işlev uygulayacağını biliyorum. Yinelemeli (ve sonlandırma koşulları bakımından, vs olmadan)Scala'daki alt listeler üzerinde haritalama

map(s, f) = f(s.head) :: map(s.tail, f) 

ben yapan bir işlev için arıyorum

foo(s, f) = f(s) :: map(s.tail, f). 

gibi bir şey Yani haritalama fonksiyonu sublists değil üzerinde çağrılan bir 'mapper' bireysel elemanlar. Lisp açısından, bir mapcar'ın aksine bir harita listesi arıyorum. Bunun gibi bir şey var mı, yoksa kendi başıma mı (veya özyinelemeyi kullanmalıyım) mi?

Alternatif olarak, girdi olarak bir diziyi alır ve orta uca altsekanslarına dizisi döndüren bir işlev, yani alırdım

Temelde İçinde aradığınızı tanımladığınız
bar(s, f) = s :: bar(s.tail, f) 
+0

istenen giriş ve çıkış bir örnek verebilir misiniz? Takip etmekte zorlanıyorum. –

+0

Bu sorunun cevabını bilmiyorum, ancak gelişmiş tür ve işlevlere gereksiniminiz varsa, bkz. Scalaz kitaplığı: http://code.google.com/p/scalaz/ – egaga

cevap

5

/* Bu yaklaşım mapList'i kuyruk adı verilen başka bir kullanışlı yöntem olarak tanımlar. Daniel gibi, ben Listeye örtük bir uzantısı koyacağım, ama bu/tamamen tat * meselesi

implicit def richerList[A](list : List[A]) = new { 

/* Burada listedeki her olası kuyruk döndüren kuyrukları denilen bir yöntem. Bu kuyruk özyinelemedir, bu yüzden büyük listelerde patlamaz. Aynı ismin Haskell işlevinden biraz farklı olduğunu unutmayın. Haskell versiyonu daima sonuca boş listesini ekler *

def tails : List[List[A]] = { 
    def loop(ls : List[A], accum : List[List[A]]) : List[List[A]] = ls match { 
     case _ :: tail => loop(tail, ls :: accum) 
     case _ => accum 
    } 

    loop(list, Nil).reverse 
    } 

/

/* Bu kuyrukları kullanmak gibi

scala> "abc".toList.tails 
res0: List[List[Char]] = List(List(a, b, c), List(b, c), List(c)) 

*/

/* Artık tanımlayabiliriz mapList görünüyor ne kuyrukları dayalı */

def mapList[B](f : List[A] => B) = tails map f 
} 

/* Ve bu kullanarak mapList

neye benzediği
scala> "abc".toList mapList (_.reverse.mkString) 
res1: List[String] = List(cba, cb, c) 

*/

2

pseudocode - bu örtük dönüşümleri kullanarak Scala listesine böyle bir yöntem eklemek kolaydır böylece:

object ExtendedList{ 
    implicit def List2ExtendedList[A](l:List[A])=new ExtendedList(l) 
} 
class ExtendedList[A](l:List[A]){ 
    import ExtendedList._ 
    def mapList[B](f:List[A]=>B):List[B]=l.length match { 
    case 0 => List() 
    case _ => f(l)::l.tail.mapList(f) 
    } 
} 

object Test extends Application{ 
    import ExtendedList._ 
    val test = List(5,4,3,2,1) 
    assert(List(15,10,6,3,1)==test.mapList{l=>(0/:l){_+_}}) 
} 

bu aradığınız şey bu mu?

+0

Bu O (n) almak için Bir listenin uzunluğu ve haritanızL, n (2 (2) maliyet için n kere yapar. Bunu büyük bir liste üzerinde çalıştırın ve bir süre bekleyeceksiniz :-) –

+0

Sormamın nedeni, Scala için yeni olduğum ve yerleşik bir kanonik işlev olup olmadığını öğrenmek istedim (kodumu daha okunabilir hale getirmek için) diğerleri). Alternatif olarak, bunu yapmak istemiyorum, bunu yapmanın scala yolu ___ " – bsdfish

+0

Yup, kullanmanın onaylandığını biliyorum. Kötü bir şey - daha fazla düşünmeliydim!" –

1

Diğer cevap yakındadır, ancak kesinlikle gerekli olmadıkça aslaList#length kullanmalısınız. Sorun, O (n) numaralı telefondan bağımsız olarak, çözümünü O (n^2) yapar. Orijinal soruyu cevaplamak için,

implicit def addListSyntax[A](list: List[A]) = new { 
    def mapList[B](f: List[A]=>B) = { 
    // use inner function to avoid repeated conversions 
    def loop(list: List[A]): List[B] = list match { 
     case ls @ (_ :: tail) => f(ls) :: loop(tail) 
     case Nil => Nil 
    } 

    loop(list) 
    } 
} 

Ve: İşte temizlenmiş versiyonu hayır, standart yarar yöntemler kullanarak bunu yapmanın bir yolu yoktur. Aslında neden böyle bir şey isteyeceğini merak ediyorum ...

+1

Bu sürüm kuyruk özyineli olmadığından dikkatli olun. Büyük listeler yığın patlamasına neden olur. –

+0

Gerçekten de, bu büyük bir hata. – egaga

+0

Sıralı zaman damgalarının bir listesi var ve - her bir zaman damgası ve y önceki zaman damgaları - her zaman damgası, her zaman damgası ile birlikte, ondan önceki x dakika için eşleştirmem gerekiyor. Yine, birden fazla yolla nasıl kodlanacağını biliyorum (kendi harita listesini tanımlayarak, zorunlu olarak, haritayı kullanarak ve sonra içeriğin içine filtre uygulayarak, vb.), Ancak bunu nasıl temizleyeceğimi ve Scala'nın nasıl yapıldığını öğrenmek istedim. yol. – bsdfish