假设我有一个功能:
def f(i: Int): String = i.toString
如何定义 xxx ,例如(假设我可以在没有隐式转换的情况下添加列表方法):
val source1: List[List[Int]] = List(List(1,2), List(3,4))
val source2: List[Int] = List(1,2)
val result1: List[List[String]] = source1.xxx(f)
val result2: List[String] = source2.xxx(f)
因为
列出[_]
我无法判断_是否可以应用地图。有可能吗?
答案 0 :(得分:1)
你可以试试这个:
object Container1 {
implicit class RichList1(l: List[List[Int]]) {
def xxx(f: (Int) => String): List[List[String]] = {
l.map(l => l.map(n => f(n)))
}
}
}
object Container2 {
implicit class RichList2(l: List[Int]) {
def xxx(f: (Int) => String): List[String] = {
l.map(n => f(n))
}
}
}
object Mapping extends App {
def f(i: Int): String = i.toString
val source1: List[List[Int]] = List(List(1, 2), List(3, 4))
val source2: List[Int] = List(1, 2)
import Container1._
val result1a: List[List[String]] = source1.xxx(f)
println(result1a)
import Container2._
val result2a: List[String] = source2.xxx(f)
println(result2a)
}
答案 1 :(得分:1)
看起来您正在尝试将函数应用于集合的最内层项,无论您嵌套的值有多深(在本例中为List[T]
和List[List[T]]
)。
trait CanMapInner[WrappedV, WrappedB, V, B] {
def mapInner(in: WrappedV, f: V ⇒ B): WrappedB
}
// simple base case (no nesting involved).
implicit def simpleMapper[V, B] = new CanMapInner[V, B, V, B] {
def mapInner(in: V, f: (V) ⇒ B): B = f(in)
}
// drill down one level of "List".
implicit def wrappedMapper[V, B, InnerV, InnerB](implicit innerMapper: CanMapInner[InnerV, InnerB, V, B]) =
new CanMapInner[List[InnerV], List[InnerB], V, B] {
def mapInner(in: List[InnerV], f: (V) ⇒ B): List[InnerB] =
in.map(innerMapper.mapInner(_, f))
}
implicit class XXX[WrappedV](list: List[WrappedV]) {
def xxx[V, B, WrappedB](f: V ⇒ B)(implicit mapper: CanMapInner[WrappedV, WrappedB, V, B]) = {
list.map(inner ⇒ mapper.mapInner(inner, f))
}
}
用法:
def f(i: Int): String = "Hello " + i.toString
val source1: List[List[Int]] = List(List(1, 2), List(3, 4))
val source2: List[Int] = List(1, 2)
val result1: List[List[String]] = source1.xxx(f)
val result2: List[String] = source2.xxx(f)
Console println source1
// > List(List(1, 2), List(3, 4))
Console println source2
// > List(1, 2)
Console println result1
// > List(List(Hello 1, Hello 2), List(Hello 3, Hello 4))
Console println result2
// > List(Hello 1, Hello 2)
为了演示目的,我更改了您的f
功能。
答案 2 :(得分:0)
你可以使用无形'Scrap Your Boilerplate来做到这一点。从自述文件中复制的示例:
val nested = List(Option(List(Option(List(Option(23))))))
val succ = everywhere(inc)(nested)
succ == List(Option(List(Option(List(Option(24))))))
如果您准备好包含库来执行此操作,请由您自己决定。