与Any => List [Any] => List [Long]

时间:2019-05-02 19:58:19

标签: scala

使用Scala,我试图对返回值类型为Any的类进行模式匹配,以提取任何List[Any]并对List[Long]List[Double]进行模式匹配。

有没有更优雅的方式做到这一点?

运行scala 2.11

case class Accumulator (
    name: Option[String],
    value: Option[Any]
)

def bar[T <: Any](value: T): Unit = {
    val listOfAny = value.asInstanceOf[List[Any]]
    val listOfTypes = listOfAny.map(x => x.getClass.getSimpleName).toSet

    listOfTypes.size match {
        case 1 => listOfTypes.head match {
            case "Long" => println("Long list")
            case "Double" => println("Double list")
            case _ => Unit
        }
        case _ => Unit //Probably throw an error log
    }
}

def foo(accumulator: Accumulator): Unit = {
    accumulator match {
        case Accumulator(_, Some(value)) => value match {
            case v if v.isInstanceOf[List[_]] => bar(v)
            case _ => Unit
        }
        case _ => Unit
    }
}


//Should print out "Long List"
foo(Accumulator(None, Some(List(1L, 2L, 3L))))
//Should print out "Double List"
foo(Accumulator(None, Some(List(1.0, 2.0, 3.0))))

编辑:

能够清理带有稳定标识符的字符串

case class Accumulator (
    name: Option[String],
    value: Option[Any]
)

def bar[T <: Any](value: T): Unit = {
    val listOfAny = value.asInstanceOf[List[Any]]
    val listOfTypes = listOfAny.map(x => x.getClass).toSet

    listOfTypes.size match {
        case 1 => 
            val headType: Class[_] = listOfTypes.head

            // Stable identifiers
            val ClassOfLong: Class[java.lang.Long] = classOf[java.lang.Long]
            val ClassOfDouble: Class[java.lang.Double] = classOf[java.lang.Double]

            headType match {
                case ClassOfLong => 
                    val result: Long = listOfAny.asInstanceOf[List[Long]].sum
                    println(s"Long List sum: $result")
                case ClassOfDouble =>
                    val result: Double = listOfAny.asInstanceOf[List[Double]].sum
                    println(s"Double List sum: $result")
                case _ => Unit
        }
        case _ => Unit //Probably throw an error log
    }
}

def foo(accumulator: Accumulator): Unit = {
    accumulator match {
        case Accumulator(_, Some(value)) => value match {
            case v if v.isInstanceOf[List[_]] => bar(v)
            case _ => Unit
        }
        case _ => Unit
    }
}


//Should print out "Long List sum: 6"
foo(Accumulator(None, Some(List(1L, 2L, 3L))))
//Should print out "Double List sum: 6.0"
foo(Accumulator(None, Some(List(1.0, 2.0, 3.0))))

2 个答案:

答案 0 :(得分:0)

如果列表不为空并且所有元素都属于同一类型,则可以将返回的对象与列表中的第一个元素匹配。像这样

def surprise(): Any = Random.nextInt(3) match {
  case 0 => List(1L, 2L, 3L)
  case 1 => List(0.5, 1.5, 2.5)
  case _ => "foo"
}

0 to 10 foreach { _ =>
  surprise() match {
    case l @ List(_: Long, _*) =>
      println(s"Longs: $l")
    case l @ List(_: Double, _*) =>
      println(s"Doubles: $l")
    case x =>
      println(s"Something else: $x")
  }
}

输出:

"""
Something else: foo
Something else: foo
Longs: List(1, 2, 3)
Doubles: List(0.5, 1.5, 2.5)
Doubles: List(0.5, 1.5, 2.5)
Doubles: List(0.5, 1.5, 2.5)
Doubles: List(0.5, 1.5, 2.5)
Doubles: List(0.5, 1.5, 2.5)
Something else: foo
Longs: List(1, 2, 3)
Something else: foo
"""

答案 1 :(得分:0)

case class Accumulator (
    name: Option[String],
    value: Option[Any]
)

def bar[T <: Any](value: T): Unit = {
    val listOfAny = value.asInstanceOf[List[Any]]
    val listOfTypes = listOfAny.map(x => x.getClass).toSet

    listOfTypes.size match {
        case 1 => 
            val headType: Class[_] = listOfTypes.head

            // Stable identifiers
            val ClassOfLong: Class[java.lang.Long] = classOf[java.lang.Long]
            val ClassOfDouble: Class[java.lang.Double] = classOf[java.lang.Double]

            headType match {
                case ClassOfLong => 
                    val result: Long = listOfAny.asInstanceOf[List[Long]].sum
                    println(s"Long List sum: $result")
                case ClassOfDouble =>
                    val result: Double = listOfAny.asInstanceOf[List[Double]].sum
                    println(s"Double List sum: $result")
                case _ => Unit
        }
        case _ => Unit //Probably throw an error log
    }
}

def foo(accumulator: Accumulator): Unit = {
    accumulator match {
        case Accumulator(_, Some(value)) => value match {
            case v if v.isInstanceOf[List[_]] => bar(v)
            case _ => Unit
        }
        case _ => Unit
    }
}


//Should print out "Long List sum: 6"
foo(Accumulator(None, Some(List(1L, 2L, 3L))))
//Should print out "Double List sum: 6.0"
foo(Accumulator(None, Some(List(1.0, 2.0, 3.0))))