scala - 迭代器:将最后一个元素与不同的值配对
问题描述
在 Scala 中,我有一个 List[String] ,如下所示:
val xs = List("apple", "orange", ..., "pear", "dragonfruit")
我想生成以下结果列表:
List(("apple", ","), ("orange", ","), ..., ("pear", ","), ("dragonfruit", ";"))
请注意,最后一对有一个分号而不是逗号。我可以在不知道列表长度的情况下执行此操作吗?更一般地说,是否有适用于 Iterable 的功能版本?
def pairUp[A,B](xs: Iterable[A], nonlastB: B, lastB: B): Iterable[(A,B)]
除了最后一个 xs 中的每个 x 都应该与 配对nonlastB
,最后一个与lastB
.
解决方案
用于foldRight
此。
在您的示例中,您有
"apple" :: "orange" :: ... :: "pear" :: "dragonfruit" :: Nil
而你想要
("apple", ",") :: ("orange", ",") :: ... :: ("pear", ",") :: ("dragonfruit", ";") :: Nil
foldRight 的直觉是它会替换构造函数。
l.foldRight
接受两个参数。第一个替换了构造函数Nil
,第二个替换了构造函数::
,所以你有l.foldRight(nilReplacement)(consreplacement)
现在让我们看看你想要什么替换 forNil
和 for ::
:
"apple" :: "orange" :: ... :: "pear" :: "dragonfruit" :: Nil
("apple", ",") :: ("orange", ",") :: ... :: ("pear", ",") :: ("dragonfruit", ";") :: Nil
Nil
停留Nil
x :: Nil
变成(x, ";") :: Nil
x :: other
变成(x, ",") :: other
所以
val nilReplacement = Nil
val consReplacement = {
case x :: Nil => (x, ";") :: Nil
case x :: other => (x, ",") :: other
}
xs.foldRight(nilReplacement)(consReplacement)
不幸的是,您会发现val consreplacement
由于没有预期的类型而无法正确进行类型检查,并且它Nil
很快就会推断出错误的类型。但是给它足够的类型提示可以解决这个问题:
xs.foldRight[(String, String)](Nil) {
case x :: Nil => (x, ";") :: Nil
case x :: other => (x, ",") :: other
}
一种完全不同的方法通过迭代直接进行:
import scala.collection.mutable.Builder
def pairUp[A,B](as: Iterable[A], nonlastB: B, lastB: B): Iterable[(A,B)] = {
val it = as.iterator
val builder = as.iterableFactory.newBuilder[(A, B)]
def loop(prev: A): Unit = {
if (it.hasNext) {
builder.addOne(prev -> nonlastB)
loop(it.next())
} else builder.addOne(prev -> lastB)
}
if(it.hasNext) loop(it.next())
builder.result()
}
您可以使用Factory
stdlib 中有些复杂的基础结构来抽象输入类型:
def pairUpF[A,B, F[x] <: IterableOps[x, F, F[x]]](as: F[A], nonlastB: B, lastB: B): F[(A,B)] = {
val it = as.iterator
val builder = as.iterableFactory.newBuilder[(A, B)]
def loop(prev: A): Unit = {
if (it.hasNext) {
builder.addOne(prev -> nonlastB)
loop(it.next())
} else builder.addOne(prev -> lastB)
}
if(it.hasNext) loop(it.next())
builder.result()
}
推荐阅读
- neo4j - 在 Neo4j 中查找集群
- arrays - 使用“vbnewline”Visual Basic 吐出 2D 数组
- translation - ABAP:术语表
- tensorflow - 为什么 tf.metric 返回零?
- matlab - 如何更改MATLAB图形工具栏上的按钮图标?(2014b)
- xamarin - 有没有一种方法可以确定显示大小并使用它来调整带有 Xamarin Forms 的字体的高度?
- java - Spring Redis 反序列化在不可变属性上失败
- flutter - Flutter - 无法编辑 pubspec.yaml 文件
- c - C中的赋值
- windows - 如何在 Windows 中循环处理 FFMpeg?