У меня есть фрейм данных 'regexDf', как показано ниже
id,regex
1,(.*)text1(.*)text2(.*)text3(.*)text4(.*)|(.*)text2(.*)text5(.*)text6(.*)
2,(.*)text1(.*)text5(.*)text6(.*)|(.*)text2(.*)
Если длина регулярного выражения превышает некоторую максимальную длину, например, 50, то я хочу удалить последний текстовый токен в разделенной строке регулярного выражения, разделенной символом '|' для превышенного идентификатора. В приведенном выше фрейме данных длина id 1 превышает 50, поэтому последние токены 'text4 (. )' и 'text6 (. )' из каждой разделенной строки регулярного выражения должны быть удалены. Даже после удаления этого значения длина строки регулярного выражения в id 1 по-прежнему превышает 50, так что снова нужно удалить последние токены 'text3 (. )' и 'text5 (. )'. Таким образом, окончательный кадр данных будет
id,regex
1,(.*)text1(.*)text2(.*)|(.*)text2(.*)
2,(.*)text1(.*)text5(.*)text6(.*)|(.*)text2(.*)
Я могу обрезать последние токены, используя следующий код
val reducedStr = regex.split("|").foldLeft(List[String]()) {
(regexStr,eachRegex) => {
regexStr :+ eachRegex.replaceAll("\\(\\.\\*\\)\\w+\\(\\.\\*\\)$", "\\(\\.\\*\\)")
}
}.mkString("|")
Я пытался использовать цикл while для проверки длины и обрезки текстовых токенов в итерации, которая не работает. Также я хочу избежать использования var и while. Можно ли добиться без цикла while.
val optimizeRegexString = udf((regex: String) => {
if(regex.length >= 50) {
var len = regex.length;
var resultStr: String = ""
while(len >= maxLength) {
val reducedStr = regex.split("|").foldLeft(List[String]()) {
(regexStr,eachRegex) => {
regexStr :+ eachRegex
.replaceAll("\\(\\.\\*\\)\\w+\\(\\.\\*\\)$", "\\(\\.\\*\\)")
}
}.mkString("|")
len = reducedStr.length
resultStr = reducedStr
}
resultStr
} else {
regex
}
})
regexDf.withColumn("optimizedRegex", optimizeRegexString(col("regex")))
Согласно предложению Сатьяна и Паша, я изменил рекурсивный метод как функцию.
def optimizeRegex(regexDf: DataFrame): DataFrame = {
val shrinkString= (s: String) => {
if (s.length > 50) {
val extractedString: String = shrinkString(s.split("\\|")
.map(s => s.substring(0, s.lastIndexOf("text"))).mkString("|"))
extractedString
}
else s
}
def shrinkUdf = udf((regex: String) => shrinkString(regex))
regexDf.withColumn("regexString", shrinkUdf(col("regex")))
}
Теперь я получаю исключение, так как "рекурсивное значение shrinkString нуждается в типе"
Error:(145, 39) recursive value shrinkString needs type
val extractedString: String = shrinkString(s.split("\\|")
.map(s => s.substring(0, s.lastIndexOf("text"))).mkString("|"));