有没有一种方法可以将默认案例值作为参数传递

时间:2020-09-18 17:35:47

标签: scala apache-spark

我正在尝试查看是否有一种方法可以将默认大小写的值合并到匹配表达式中

item match {
case null => false
case _:String => _.matches(params)
}

我曾尝试寻找其他选项,但我找不到真正的解决方案。

对于上下文,这是此代码段的一部分,在spark dataframe上执行

x.filter(row => row.getAs[String]("colname").matches("""/regex/""")).count()

但是有些偶然的null值会破坏一切。

我知道我可以这样做以获得期望的结果,但是重新计算它没有意义

x.filter(row => row.getAs[String]("colname") match{
         case null => false
         case _ => row.getAs[String]("colname").matches("""\d""")
         }).count()

任何建议或指示都会有所帮助。谢谢

4 个答案:

答案 0 :(得分:2)

要匹配所有内容,您只需要使用变量名而不输入类型说明即可

item match {
   case null => false
   case i => i.matches(params)
}

所以在您的情况下:

x.filter(row => 
   row.getAs[String]("colname") match {
         case null => false
         case r => r.matches("""\d""")
   }
).count()

如果要检查项目是否为空,还可以使用Option.apply,如果值为None,则返回null,否则返回Some,例如:

Option(item).fold(false)(_.matches(params))

答案 1 :(得分:1)

除了KrzysztofAtłasik答案外,您还可以在比赛陈述之前添加对null的检查,还可以:

x
.where($"colname".isNotNull)
.filter(row => row.getAs[String]("colname").matches("""/regex/""")).count()

或类似的

x.where($"colname" rlike """\d""").count()

答案 2 :(得分:1)

您可以只使用rlike。例如:

x.filter(x("colName").rlike("cat|dog")).count

答案 3 :(得分:-1)

如果我正确地理解了您的需求,那么您正在寻求在单个迭代中进行过滤和聚合,并且我认为UDAF是您必须要做的事情。从本质上讲,与原始帖子末尾提到的选项(即udf过滤掉然后计数)相比,我认为这样做没有任何性能优势。但是,我已经演示了如何在此处使用UDAF。

对于Spark <3.0,您将必须扩展UserDefinedAggregateFunction类,使其看起来像这样-

    import org.apache.spark.sql.Row
    import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
    import org.apache.spark.sql.types._

    class ConditionalCount(val pattern: String, colName: String) extends UserDefinedAggregateFunction{
      override def inputSchema: StructType = StructType(Seq(StructField(colName, StringType)))

      override def bufferSchema: StructType = StructType(Seq(StructField("count", LongType)))

      override def dataType: DataType = LongType

      override def deterministic: Boolean = true

      override def initialize(buffer: MutableAggregationBuffer): Unit = buffer(0) = 0L

      override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
        buffer(0) = buffer.getAs[Long](0) + input.getAs[String](0) match {
          case null => 0
          case x if x.matches(pattern) => 1L
          case _ => 0L
        }
      }

      override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit =
        buffer1(0) = buffer1.getAs[Long](0) + buffer2.getAs[Long](0)

      override def evaluate(buffer: Row): Any = buffer.getAs[Long](0)
    }


然后使用此初始化并使用此UDAF看起来像这样-


    val conditionalCount = new ConditionalCount("my pattern", "colName")

    df.withColumn("count", conditionalCount(col("colName")))

P.S .:我尚未运行并进行验证,如果有微小错误,请原谅我