Как заменить разделитель, который появляется только между чем-то? - PullRequest
2 голосов
/ 16 апреля 2020

У меня есть сценарий использования с этими данными:

1. "apple+case"
2. "apple+case+10+cover"
3. "apple+case+10++cover"
4. "+apple"
5. "iphone8+"

В настоящее время я делаю это для замены + пробелом следующим образом:

def normalizer(value: String): String = {
    if (value == null) {
      null
    } else {
       value.replaceAll("\\+", BLANK_SPACE)        
     }
  }

  val testUDF = udf(normalizer(_: String): String)

  df.withColumn("newCol",  testUDF($"value"))

Но это заменяет все "+". Как заменить «+», который находится между строками, а также обрабатывать варианты использования, такие как: «apple + case + 10 ++ cover» => «apple case 10+ cover»?

The output should be
1. "apple case"
2. "apple case 10 cover"
3. "apple case 10+ cover"
4. "apple"
5. "iphone8+"

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Вы можете использовать regexp_replace, чтобы сделать это вместо udf, это должно быть намного быстрее. В большинстве случаев вы можете использовать отрицательное предположение в регулярном выражении, но для «+ apple» вы на самом деле хотите заменить «+» на «» (а не пробел). Самый простой способ - просто использовать регулярные выражения.

df.withColumn("newCol", regexp_replace($"value", "^\\+", ""))
  .withColumn("newCol", regexp_replace($"newCol", "\\+(?!\\+|$)", " "))

Это даст:

+--------------------+--------------------+
|value               |newCol              |
+--------------------+--------------------+
|apple+case          |apple case          |
|apple+case+10+cover |apple case 10 cover |
|apple+case+10++cover|apple case 10+ cover|
|+apple              |apple               |
|iphone8+            |iphone8+            |
+--------------------+--------------------+

Чтобы сделать это более модульным и многократно используемым, вы можете определить его как функцию :

def normalizer(c: String) = regexp_replace(regexp_replace(col(c), "^\\+", ""), "\\+(?!\\+|$)", " ")

df.withColumn("newCol", normalizer("value"))
0 голосов
/ 16 апреля 2020

Вы можете попробовать сделать две замены регулярных выражений:

df.withColumn("newCol", regexp_replace(
    regexp_replace(testUDF("value"), "(?<=\d)\+(?!\+)", "+ "),
    "(?<!\d)\+", " ")).show

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

apple+case+10+cover  -->  apple+case+10+ cover

Затем замена внешнего регулярного выражения нацеливается на все плюсы, которым не предшествует ди git, и заменяет их пробелом. Пример, продолжение сверху:

apple+case+10+ cover -->  apple case 10+ cover
...