Я хочу разделить следующую строку, которая принимает форму
val str = "X|blnk_1|blnk_2|blnk_3|blnk_4|time1|time2|blnk_5|blnk_6|blnk_7|blnk_8| |Z01|Str1|01|001|NE]|[HEX1|HEX2]|[NA|001:1000|123:456|[00]|]|Z01|Str2|02|002|NE]|[HEX3|HEX4]|[NA|002:1001|234:456|[01]|]|Z02|02|z2|Str|Str|"
Эта строка всегда начинается с X, а позиции разделения - Z01, Z02, ..., Z0D.
str.split("""\|Z0[1|2|3|4|5|6|7|8|9|A|B|C|D]{1}\|""") foreach println
Здесь не может быть упорядочивания позиций Z01, ..., Z0D в строке.
Разделение дает желаемый результат:
X|blnk_1|blnk_2|blnk_3|blnk_4|time1|time2|blnk_5|blnk_6|blnk_7|blnk_8|
Str1|01|001|NE]|[HEX1|HEX2]|[NA|001:1000|123:456|[00]|]
Str2|02|002|NE]|[HEX3|HEX4]|[NA|002:1001|234:456|[01]|]
02|z2|Str|Str|
Однако я хочу сопоставить X, Z01, ... с классами case. Поскольку нет упорядочивания, невозможно определить, в какой раздел класса case необходимо сопоставить (нельзя использовать длину отдельных разделений).
Я ожидаю, что мой раскол будет иметь следующий результат:
X|blnk_1|blnk_2|blnk_3|blnk_4|time1|time2|blnk_5|blnk_6|blnk_7|blnk_8|
Z01|[Str1|01|001|NE]|[HEX1|HEX2]|[NA|001:1000|123:456|[00]|]|
Z01|[Str2|02|002|NE]|[HEX3|HEX4]|[NA|002:1001|234:456|[01]|]|
Z01|02|z2|Str|Str|
чтобы результат можно было сопоставить с классом case с помощью предварительно добавленного шаблона.
Например:
case class X( ....)
case class Z01(val1: String, val2: String, val3: String)
case class Z02(val1: Int, val2: String, val3: String,val4:String)
.................
X|blnk_1|blnk_2|blnk_3|blnk_4|time1|time2|blnk_5|blnk_6|blnk_7|blnk_8| сопоставляется с case class X
а также
Z01|[Str1|01|001|NE]|[HEX1|HEX2]|[NA|001:1000|123:456|[00]|]| соответствует классу корпуса Z01
и, в конечном итоге, результат должен быть в виде упорядоченных и похожих групп, которые следует рассматривать как массив конкретного класса case.
X
Array[Z01]
Array[Z02]
......
......
@Jatin Это фактически часть преобразования фрейма данных Spark. Я бы хотел сделать это за один проход.
Я не могу это подтвердить. Но может потребоваться меньшее количество тактовых циклов. Regex - серийный убийца времени. Разделение на один символ не вызывает внутреннее выражение регулярного выражения, а простую итерацию строки





Как насчет этой идеи?
val x = str.split("""\|Z0[1|2|3|4|5|6|7|8|9|A|B|C|D]{1}\|""") // actual string splits
val y = """\|Z0[1|2|3|4|5|6|7|8|9|A|B|C|D]{1}\|""".r.findAllIn(str).toArray // delimiters Array
val final_data = x.slice(1, x.size).zip(y).map(x => x._2+x._1).toList // taking actual splits except first one .... and then zipping and concatenating with delimiters like below.
/*
List(|Z01|Str1|01|001|NE]|[HEX1|HEX2]|[NA|001:1000|123:456|[00]|], |Z01|Str2|02|002|NE]|[HEX3|HEX4]|[NA|002:1001|234:456|[01]|], |Z02|02|z2|Str|Str|) */
первый | в final_data может быть удален с помощью subString
В качестве альтернативы это может быть вариант получения ваших значений путем их сопоставления:
(?:Z0[1-9A-D]|^X).*?(?=\|Z0[1-9A-D]|$)
Это соответствует:
(?:Z0[1-9A-D]|X\|) В группе без захвата сопоставьте Z0 и перечислите возможные варианты в классе символов или | X в начале ^ строки.*? Соответствует любому символу один или несколько раз не жадно(?=\|Z0[1-9A-D]|$) Положительный просмотр вперед, который утверждает, что далее следует вертикальная черта |, за которой следует Z0 и символ из списка символов или | в конце строки $.Например:
val re = """(?:Z0[1-9A-D]|^X).*?(?=\|Z0[1-9A-D]|$)""".r
val str = "X|blnk_1|blnk_2|blnk_3|blnk_4|time1|time2|blnk_5|blnk_6|blnk_7|blnk_8| |Z01|Str1|01|001|NE]|[HEX1|HEX2]|[NA|001:1000|123:456|[00]|]|Z01|Str2|02|002|NE]|[HEX3|HEX4]|[NA|002:1001|234:456|[01]|]|Z02|02|z2|Str|Str|"
re.findAllIn(str) foreach println
Это приведет к:
X|blnk_1|blnk_2|blnk_3|blnk_4|time1|time2|blnk_5|blnk_6|blnk_7|blnk_8|
Z01|Str1|01|001|NE]|[HEX1|HEX2]|[NA|001:1000|123:456|[00]|]
Z01|Str2|02|002|NE]|[HEX3|HEX4]|[NA|002:1001|234:456|[01]|]
Z02|02|z2|Str|Str|
Как насчет простого на вид
str.split("Z"), а затем его ручного анализа?