2016-03-29 23 views
0
ben bir dizin ve alt dizinleri her dosya için bir işlev uygulamak istediğiniz

işlemek için:scala akışı yinelemeli, dosya ve alt dizinleri

def applyRecursively(dir: String, fn: (File) => Any) { 
    def listAndProcess(dir: File) { 
     dir.listFiles match { 
     case null => out.println("exception: dir cannot be listed: " + dir.getPath); List[File]() 
     case files => files.toList.sortBy(_.getName).foreach(file => { 
      fn(file) 
      if (file.isDirectory) listAndProcess(file) 
     }) 
     } 
    } 
    listAndProcess(new File(dir)) 
    } 

    def exampleFn(file: File) { println(s"processing $file") } 

    applyRecursively(dir, exampleFn) 

bu çalışır. Önceden answered scala Iteratees kullanarak bu kodu nasıl refactor. Buradaki soru, bu kodu scala Streams kullanarak nasıl yeniden oluşturabilirim. Böyle şey: Burada

val stream: Stream[File] = ... // ??? 
stream.foreach(exampleFn) 
+0

'her dosya' için bir işlev uygulamak - her dosya için, ya her dosya veya-alt dizin için? fn (dosya) 'da alt dizinlere de çağrılmalıdır? –

cevap

3

gitmek:

def fileStream(dir: File): Stream[File] = 
    Option(dir.listFiles).map(_.toList.sortBy(_.getName).toStream).map { 
    files => files.append(files.filter(_.isDirectory).flatMap(fileStream)) 
    } getOrElse { 
    println("exception: dir cannot be listed: " + dir.getPath) 
    Stream.empty 
    } 

Güncelleme: getiriler hem dosyaları ve dizinleri yukarıda Uygulama.

def fileStreamNoDirs(dir: File): Stream[File] = 
    Option(dir.listFiles).map(_.toList.sortBy(_.getName).toStream.partition(_.isDirectory)) 
    .map { case (dirs, files) => 
     files.append(dirs.flatMap(fileStreamNoDirs)) 
    } getOrElse { 
    println("exception: dir cannot be listed: " + dir.getPath) 
    Stream.empty 
    } 

Ancak basit fileStream("/some/path").filterNot(_.isDirectory) aynı işi yapar: Burada verimli dizinleri hariç nasıl olduğunu.

Update2

: Bu varyant orijinal örnek geçişi sırasını korur:

def fileStream(dir: File): Stream[File] = 
    if (dir.isDirectory) 
    Option(dir.listFiles) 
     .map(_.toList.sortBy(_.getName).toStream.flatMap(file => file #:: fileStream(file))) 
     .getOrElse { 
     println("exception: dir cannot be listed: " + dir.getPath) 
     Stream.empty 
     } 
    else Stream.empty 
+0

alt dizinleri kendilerini dosya listesine dahil etmeyecek mi? Verilmiş, konu stater orijinal kodu da dizinleri üzerinden fn 'çağırır, ama onun soru metninin onun niyetini değil .... –

+1

@ Arioch'The, iyi bir nokta. Güncellenmiş. – Aivean

+0

evet, sağlanan kodda olduğu gibi, alt dizinleri dosya listesine eklemek istedim. Sorunun metni için üzgünüm. –

İlgili konular