Fre*_*Foo 3 scala yield list-comprehension
我正在尝试学习Scala,并尝试编写一个序列理解,从序列中提取unigrams,bigrams和trigrams.例如,[1,2,3,4]应该转换为(不是Scala语法)
[1; _,1; _,_,1; 2; 1,2; _,1,2; 3; 2,3; 1,2,3; 4; 3,4; 2,3,4]
Run Code Online (Sandbox Code Playgroud)
在Scala 2.8中,我尝试了以下方法:
def trigrams(tokens : Seq[T]) = {
var t1 : Option[T] = None
var t2 : Option[T] = None
for (t3 <- tokens) {
yield t3
yield (t2,t3)
yield (t1,t2,Some(t3))
t1 = t2
t2 = t3
}
}
Run Code Online (Sandbox Code Playgroud)
但是这并没有编译,因为显然,yield在一个for理解中只允许一个(也没有块语句).有没有其他优雅的方法来获得相同的行为,只有一次传递数据?
for循环中不能有多个yield,因为for循环是map(或flatMap)操作的语法糖:
for (i <- collection) yield( func(i) )
Run Code Online (Sandbox Code Playgroud)
翻译成
collection map {i => func(i)}
Run Code Online (Sandbox Code Playgroud)
没有收益
for (i <- collection) func(i)
Run Code Online (Sandbox Code Playgroud)
翻译成
collection foreach {i => func(i)}
Run Code Online (Sandbox Code Playgroud)
因此,整个身体for循环变成一个单个封闭,并且存在yield关键字确定呼吁收集功能是否是map或foreach(或者flatMap).由于此翻译,禁止以下内容:
yield来确定将产生什么.(更不用说你提出的verison会返回一个,List[Any]因为元组和1-gram都是不同的类型.你可能想得到一个List[List[Int]]代替)
请尝试以下方法(将n-gram按其出现的顺序排列):
val basis = List(1,2,3,4)
val slidingIterators = 1 to 4 map (basis sliding _)
for {onegram <- basis
ngram <- slidingIterators if ngram.hasNext}
yield (ngram.next)
Run Code Online (Sandbox Code Playgroud)
要么
val basis = List(1,2,3,4)
val slidingIterators = 1 to 4 map (basis sliding _)
val first=slidingIterators head
val buf=new ListBuffer[List[Int]]
while (first.hasNext)
for (i <- slidingIterators)
if (i.hasNext)
buf += i.next
Run Code Online (Sandbox Code Playgroud)
如果您希望n-gram为长度顺序,请尝试:
val basis = List(1,2,3,4)
1 to 4 flatMap { basis sliding _ toList }
Run Code Online (Sandbox Code Playgroud)