#python #regex #apache-spark #pyspark
#python #регулярное выражение #apache-spark #pyspark
Вопрос:
Мне нужно удалить нули, которые находятся в середине строки, сохранив те, что в конце (в pyspark). Пока я нашел только регулярное выражение, которое удаляет начальные или конечные нули. Пример:
df1 = spark.createDataFrame(
[
("GH0786",),
("HH7040",),
("IP0090",),
("AH567",),
],
["number"]
)
ВВОД:
-------
|number |
-------
|GH0786 |
|HH7040 |
|IP0090 |
|AH567 |
-------
ОЖИДАЕМЫЙ РЕЗУЛЬТАТ:
-------
|number |
-------
|GH786 |
|HH740 |
|IP90 |
|AH567 |
-------
Я думал о разделении строки по первому нулю и удалении последнего символа (0) первой подстроки (и если первый символ второй подстроки также начинается с нуля, тогда удалите первый символ), но мне было интересно, есть ли более элегантный способ.
Комментарии:
1. https://regex101.com / — отличный сайт, где вы можете создавать и тестировать регулярные выражения — я полагаю, что в итоге у вас может получиться что-то вроде этого:
r"(?<=.)(0 )(?=.)"
2. Пример «IP0090» кажется неправильным, согласно вашему вопросу, это должно быть «IP009», а не «IP900»
Ответ №1:
Вы можете использовать 0 (?!$)
для сопоставления нулей, которых нет в конце строк; ?!
означает отрицательный взгляд вперед, $
соответствует концу строки, поэтому (?!$)
соответствует символу, которого нет в EOS:
import pyspark.sql.functions as F
df1.withColumn('zeroRemoved', F.regexp_replace('number', '0 (?!$)', '')).show()
------ -----------
|number|zeroRemoved|
------ -----------
|GH0786| GH786|
|HH7040| HH740|
|IP0090| IP90|
| AH567| AH567|
------ -----------
Ответ №2:
regex_replace
Метод предпочтительнее, но вы также могли бы использовать udf
для этого:
from pyspark.sql.functions import col, udf
from pyspark.sql.Types import StringType
def remove_inner_zeroes(my_string):
if my_string[-1] == '0':
return my_string.replace('0', '') '0'
return my_string.replace('0', '')
remove_inner_zeros_udf = udf(remove_inner_zeros, StringType())
df1.withColumn('zeroRemoved', remove_inner_zeros_udf(col('number')).show()
# ------ -----------
#|number|zeroRemoved|
# ------ -----------
#|GH0786| GH786|
#|HH7040| HH740|
#|IP0090| IP90|
#| AH567| AH567|
# ------ -----------
Или вы могли бы повторить ту же функциональность, используя следующие функции spark:
pyspark.sql.Columns.endsWith()
pyspark.sql.functions.replace()
pyspark.sql.functions.when()
pyspark.sql.functions.concat()
:
Например:
from pyspark.sql.functions import col, concat, lit, replace, when
def remove_inner_zeros_spark(string_col):
return when(
string_col.endsWith('0'),
concat(replace(string_col, '0', ''), lit('0'))
).otherwise(replace(string_col, '0', ''))
df1.withColumn('zeroRemoved', remove_inner_zeros_spark(col('number')).show()
# ------ -----------
#|number|zeroRemoved|
# ------ -----------
#|GH0786| GH786|
#|HH7040| HH740|
#|IP0090| IP90|
#| AH567| AH567|
# ------ -----------