Как взорваться в искре с разделителем - PullRequest
0 голосов
/ 05 октября 2018

У меня есть таблица:

id itemNames купоны 1 предмет (foo bar) доступен, мыло true 2 предмет (bar) доступен false 3 мыла, шампунь false 4 item (foo bar, bar) естьдоступно true 5 элемент (foo bar, bar) доступен, (мыло, шампунь) true 6 null false

Я хочу разбить это на

id itemNames купоны 1 элемент (foo bar) естьдоступно true
1 мыло true 2 предмет (гистограмма) доступно false 3 мыла false 3 позор ложно 4 предмет (foo bar, bar) доступно true 5 шт. (foo bar, bar) доступно true 6 (мыло, шампунь)true
6 null true

когда я делаю:

 df.withColumn("itemNames", explode(split($"itemNames", "[,]")))

Я получаю:

itemNames                                          coupons
item (foo bar) is available                        true       
soaps                                              true 
item (bar) is available                            false
soaps                                              false
shampoo                                            false
item (foo bar,                                     true
bar) is available                                  true 
(soap,                                             true    
shampoo)                                           true

Может кто-нибудь сказать мне, что я делаю неправильно и какя могу это исправить?Единственная распространенная здесь модель - запятая внутри ().

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

С UDF и вдохновлено Regex для сопоставления только запятых, не указанных в скобках? :

val df = List(
  ("item (foo bar) is available, soaps", true),
  ("item (bar) is available", false),
  ("soaps, shampoo", false),
  ("item (foo bar, bar) is available", true),
  ("item (foo bar, bar) is available, (soap, shampoo)", true)
).
  toDF("itemNames", "coupons")
df.show(false)

val regex = Pattern.compile(
  ",         # Match a comma\n" +
    "(?!       # only if it's not followed by...\n" +
    " [^(]*    #   any number of characters except opening parens\n" +
    " \\)      #   followed by a closing parens\n" +
    ")         # End of lookahead",
  Pattern.COMMENTS)

val customSplit = (value: String) => regex.split(value)
val customSplitUDF = udf(customSplit)
val result = df.withColumn("itemNames", explode(customSplitUDF($"itemNames")))
result.show(false)

Вывод:

+--------------------------------+-------+
|itemNames                       |coupons|
+--------------------------------+-------+
|item (foo bar) is available     |true   |
| soaps                          |true   |
|item (bar) is available         |false  |
|soaps                           |false  |
| shampoo                        |false  |
|item (foo bar, bar) is available|true   |
|item (foo bar, bar) is available|true   |
| (soap, shampoo)                |true   |
+--------------------------------+-------+

Если "trim" имеет значениетребуется, может быть легко добавлено в "customSplit".

0 голосов
/ 05 октября 2018

в вашей задаче нет шаблона для разбиения строки назад.Ниже приведен обходной путь, который подходит для данного конкретного случая.Я делю на «доступно», используя операцию lookbehind.Попробуйте это в своем фрейме данных взорвать

scala> "item (foo bar) is available, soaps".split("(?<=available),")
res41: Array[String] = Array(item (foo bar) is available, " soaps")

scala> "item (foo bar) is available, soaps".split("(?<=available),").length
res42: Int = 2

scala> "item (foo bar, bar) is available".split("(?<=available),")
res44: Array[String] = Array(item (foo bar, bar) is available)

scala> "item (foo bar, bar) is available".split("(?<=available),").length
res45: Int = 1

EDIT1

scala> "item (foo bar, bar) is empty, (soap, shampoo)".split("(?<=available|empty),").length
res1: Int = 2

scala>
...