регулярное выражение строки json во фрейме данных с использованием искры - PullRequest
1 голос
/ 03 июня 2019

У меня проблемы с получением значения из строки JSON с использованием регулярного выражения в искре.

Мой шаблон:

val st1 = """id":"(.*?)"""
val pattern = s"${'"'}$st1${'"'}"
//pattern is: "id":"(.*?)"

Моя тестовая строка в DF равна

import spark.implicits._
val jsonStr = """{"type":"x","identifier":"y","id":"1d5482864c60d5bd07919490"}"""                         
val df = sqlContext.sparkContext.parallelize(Seq(jsonStr)).toDF("request")   

Затем я пытаюсь разобрать значение id и добавить его к df через UDF, например так:

def getSubStringGroup(pattern: String) = udf((request: String) => {
  val patternWithResponseRegex = pattern.r
  var subString = request match {
    case patternWithResponseRegex(idextracted) => Array(idextracted)
    case _ => Array("na")
  }
  subString
})

val dfWithIdExtracted = df.select($"request")
  .withColumn("patternMatchGroups", getSubStringGroup(pattern)($"request"))
  .withColumn("idextracted", $"patternMatchGroups".getItem(0))
  .drop("patternMatchGroups")

Поэтому я хочу, чтобы мой df выглядел как

|------------------------------------------------------------- | ------------------------|
|      request                                                 |           id            |
|------------------------------------------------------------- | ------------------------|
|{"type":"x","identifier":"y","id":"1d5482864c60d5bd07919490"} | 1d5482864c60d5bd07919490|
| -------------------------------------------------------------|-------------------------|

Однако, когда я пробую описанный выше метод, мое совпадение возвращается как «нулевое», несмотря на работу на regex101.com

Может кто-нибудь посоветовать или предложить другой метод?Спасибо.

После решения Кшиштофа моя таблица теперь выглядит так:

|------------------------------------------------------------- | ------------------------|
|      request                                                 |           id            |
|------------------------------------------------------------- | ------------------------|
|{"type":"x","identifier":"y","id":"1d5482864c60d5bd07919490"} | "id":"1d5482864c60d5bd07919490"|
| -------------------------------------------------------------|-------------------------|

Я создал новый udf для обрезки ненужных символов и добавил его в df:

def trimId = udf((idextracted: String) => {
  val id = idextracted.drop(6).dropRight(1)
  id
})


val dfWithIdExtracted = df.select($"request")
  .withColumn("patternMatchGroups", getSubStringGroup(pattern)($"request"))
  .withColumn("idextracted", $"patternMatchGroups".getItem(0))
  .withColumn("id", trimId($"idextracted"))
  .drop("patternMatchGroups", "idextracted")

Теперь df выглядит так, как нужно.Еще раз спасибо Кшиштоф!

1 Ответ

1 голос
/ 03 июня 2019

Когда вы используете сопоставление с шаблоном с помощью регулярного выражения, вы пытаетесь сопоставить всю строку, что, очевидно, не может быть успешным. Вам лучше использовать findFirstMatchIn:

def getSubStringGroup(pattern: String) = udf((request: String) => {
   val patternWithResponseRegex = pattern.r
   patternWithResponseRegex.findFirstIn(request).map(Array(_)).getOrElse(Array("na"))
})

Вы также создаете свой шаблон очень странным образом, если у вас нет специального сценария его использования. Вы могли бы просто сделать:

val pattern = """"id":"(.*?)""""
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...