Если значения располагаются в порядке в соответствии с предпочтением слева (наивысший приоритет) справа (наименьший приоритет), а шаблоны с более низким приоритетом уже охватывают шаблоны с более высоким приоритетом (это не похоже на случай в вашем примере), вы генерируете выражение какthis
import org.apache.spark.sql._
def matched(df: DataFrame, nameArray: Seq[String], c: String = "text") = {
val matchIdx = nameArray.zipWithIndex.foldRight(lit(-1)){
case ((s, i), acc) => when(col(c) like s, lit(i)).otherwise(acc)
}
df.select(max(matchIdx)).first match {
case Row(-1) => None // No pattern matches all records
case Row(i: Int) => Some(nameArray(i))
}
}
Примеры использования:
matched(Seq("Some Name", "Name", "Name Surname").toDF("text"), Seq("Name", "Name%", "%Name%"))
// Option[String] = Some(%Name%)
У этого метода есть два преимущества:
- Требуется только одно действие.
- Сопоставление с образцом может быть короткозамкнутым.
Если предварительные условия не выполнены, вы можете
import org.apache.spark.sql.functions._
val unmatchedCount: Map[String, Long] = df.select(
nameArray.map(s => count(when(not($"text" like s), 1)).alias(s)): _*
).first.getValuesMap[Long](nameArray)
В отличие от первого подхода, он будет проверять все шаблоны, но для этого требуется только одиндействие.