2009-11-03 16 views

回答

2

我用了这一个可变的队列:

::#[email protected] off 
call scala %0 %* 
goto :eof 
::!# 
import scala.io.Source 

val lastN = 5 // I guess you'll be getting them from args, but... 
val queue = new scala.collection.mutable.Queue[String] 

if (args.length > 0) { 
    Source.fromFile(args(0)).getLines foreach { line => 
    queue.enqueue(line) 
    if (queue.size > lastN) queue.dequeue 
    } 
    for (line <- queue) 
    if (line.contains("percent")){ 
     print(line) 
    } 
} 

如果使用不可变队列,我会使用reduceLeft,但我认为没有必要为此使用不可变队列。

+0

通过网络读取整个5G文件和倾倒出去,但最后5行似乎很理想。 – copumpkin 2009-11-04 00:24:37

+0

它不是。你必须从头读取字节块,直到获得所需数量的行才能完成,使用几行堆栈 - 一个用于当前块,一个用于整体。这需要通过Java I/O库,这是非常可怕的,我不会为了付钱而不去碰它。 :-) – 2009-11-04 10:48:09

+1

除非你知道编码是固定字节长的,否则它是不可能从文件中读取的 – 2009-11-04 16:26:56

0

你会明显地要保持你在每次迭代更新的X线缓冲:

var buf: List[String] = Nil 

for (line <- ...) { 
    buf = (buf ::: List(line)) match { 
    case x :: xs if (xs.length == n) => xs 
    } 
} 
+1

难道这不是一个可怕的丑陋的方式来做同样的事情,丹尼尔做了一个可变的队列吗? (因为buf必须在循环的每次迭代中以线性时间进行复制,所以效率也很低。) – 2009-11-04 01:37:17

+1

我已经简化了匹配(为了清楚起见,我将所有情况都放在了这里)。我认为你需要阅读scala的不可变数据结构,因为不需要使用'List'进行复制。我认为这是相当*优雅*个人! – 2009-11-04 08:09:11

+1

Oxbow,buf _is_在线性时间被复制。 ':::'左边的arg总是被复制。它是'::',它不会复制任何东西。 – 2009-11-04 10:50:00

2

如果读取文件很昂贵,正如我预料的那样,它会通过网络,我会寻求文件的结尾并逐渐读取更大的块(更多关于日志文件格式的领域知识可能会给您一个更好的策略这里),直到你找到你要找的行数。

相关问题