好的,我不知道这是否可能,但是假设我们有以下列表:
List(1, 2, 3, 1)
如果我想对这个进行映射,有没有办法检查我之前是否已经有过一个值,例如在第四个值(第二个1)时,它会说已经遇到了1,然后抛出错误或其他什么。
好的,我不知道这是否可能,但是假设我们有以下列表:
List(1, 2, 3, 1)
List(1, 2, 3, 1).foldLeft(List[Int]()) {
// The item has already been encountered:
case (uniqueItems, b) if uniqueItems.contains(b) => {
// If as stated, you want to throw an exception, that's where you could do it
uniqueItems
}
// New item not seen yet:
case (uniqueItems, b) => uniqueItems :+ b
}
foldLeft在遍历序列时,会在处理每个新元素时工作,并且基于先前的结果得出一个结果。
对于每个元素,模式匹配(uniqueItems, b)
应该这样理解:uniqueItems
是“累加器”(它初始化为List[Int]()
),并将针对列表的每个项目进行更新(或不更新)。而b
则是当前正在处理的列表中的新项目。
顺便说一下,这个例子是一个(非高效的)列表上的distinct
。
List(Person("Frank", 30), Person("Eva", 24), Person("Frank", 23)...).foldLeft(List[Person]()) { case (uniqueItems, person) if uniqueItems.contains(person) => throw SomeException; case (uniqueItems, person) => uniqueItems :+ person }
- Xavier Guihotcase (uniqueItems, Person(name, age)) if uniqueItems.exists(_.name == name) => throw SomeException
。但我们有点偏离了最初的问题。 - Xavier GuihotList(1, 2, 3, 1).distinct.map (n => n*n)
// res163: List[Int] = List(1, 4, 9)
这段代码会去除重复项,然后以自我描述、简洁的方式执行映射。
fold
可能是最好的选择。问题在于每次迭代都必须携带先前元素的内存以及正在构建的 map()
结果。
List(1, 2, 3, 11).foldRight((Set[Int](),List[String]())) {case (i, (st, lst)) =>
if (st(i)) throw new Error //duplicate encountered
else (st + i, i.toString :: lst) //add to memory and map result
}._2 //pull the map result from the tuple
List
的唯一性,这其中一定有原因。 - jwvhSet[A]
来保证集合中元素的唯一性呢? - Yuval Itzchakov