kdb / q: Как объединить смежные элементы в списке строк с пробелом между ними?

#string #list #concatenation #kdb

#строка #Список #конкатенация #kdb

Вопрос:

Заранее благодарю вас за помощь! (Я исхожу из C и Python, и мне было сложно не использовать циклы while в kdb)

В kdb / q у меня есть список строк, назовем его «тест», который выглядит следующим образом. В этом списке 7 записей, и каждая запись представляет собой строку. Записи (строки) с индексами 2 и 4 пусты.

 test
"col_1:abc col_2:xyz"
"col_3:ijk"
""
"col_1:efg col_2:lmn"
""
"col_1:bah"
"col_3:muy"
 

Я хочу объединить смежные записи вместе, чтобы это выглядело так, как показано ниже. Записи рядом друг с другом соединяются пробелом, а пустые записи исчезают

 "col_1:abc col_2:xyz col_3:ijk"
"col_1:efg col_2:lmn"
"col_1:bah col_3:muy"
 

Пока это моя лучшая попытка. Я уверен, что я слишком усложняю это, и должен быть лучший способ.

 show {$[x~"";"|";x]}each test
"col_1:abc col_2:xyz"
"col_3:ijk"
"|"
"col_1:efg col_2:lmn"
"|"
"col_1:bah"
"col_3:muy"

show raze {$[x~"";"|";x]}each test
"col_1:abc col_2:xyzcol_3:ijk|col_1:efg col_2:lmn|col_1:bahcol_3:muy"

show "|" vs raze {$[x~"";"|";x]} each test
"col_1:abc col_2:xyzcol_3:ijk"
"col_1:efg col_2:lmn"
"col_1:bahcol_3:muy"
 

Я близок, но у меня нет нужного пробела, отделяющего «col_2: xyz» от «col_3: ijk» с индексом 0 нового списка, и у меня нет пробела, отделяющего «col_1: bah» от «col_3: muy» с индексом 2 нового списка. Как преодолеть эту проблему? Я действительно ценю ваши указания / подсказки, спасибо

Ответ №1:

Быстрое решение для случая выше, когда нет последовательных пустых строк

 q)"  "vs" "sv test
"col_1:abc col_2:xyz col_3:ijk"
"col_1:efg col_2:lmn"
"col_1:bah col_3:muy"
 

Комментарии:

1. Ого, спасибо за быстрое и элегантное решение! Я многому у вас учусь!

Ответ №2:

Если список строк считывается из файла, альтернативным вариантом может быть использование read1 для чтения файла в виде байтов, а не read0 для чтения в виде строк. например

 q)"  " vs {@[x;where x=0x0a;:;0x20]} read1`:test.txt
"col_1:abc col_2:xyz col_3:ijk"
"col_1:efg col_2:lmn"
"col_1:bah col_3:muy "
 

Здесь мы заменяем новые строки ( 0x0a ) пробелами ( 0x20 ), а затем разделяем на любой двойной пробел (т. Е. Если перед пустой строкой была пустая строка).

Одно из предостережений заключается в том, что если файл заканчивается новой строкой, последняя строка имеет завершающий пробел (в зависимости от того, как вы используете новый список строк, это может не иметь значения, но если это так, может удалить этот последний символ или использовать trim для удаления и т.д.)

Ответ №3:

Ваш собственный подход будет работать следующим образом:

 q)trim"|"vs" "sv{$[x~"";1#"|";x]}each test
"col_1:abc col_2:xyz col_3:ijk"
"col_1:efg col_2:lmn"
"col_1:bah col_3:muy"
 

Вот альтернатива, которая использует cut

 q){ltrim" "sv'cut[0,where""~/:x;x]}[test]
"col_1:abc col_2:xyz col_3:ijk"
"col_1:efg col_2:lmn"
"col_1:bah col_3:muy"
 

Комментарии:

1. Спасибо за помощь. Я понял первый пример, запустив код самостоятельно. Однако я не могу понять, что вы делаете с «cut» во втором решении. Я знаю, что: where «»~/: x — это, по сути, цикл, который определяет, какие записи в «test» имеют пустой символ «» и возвращает индексы 2 и 4. Но что означает 0 в cut? Единственная ссылка, которую я смог найти, находится здесь: code.kx.com/q/ref/cut который не использует формат cut[0,arg1, arg2]

2. Не беспокойтесь. Во-первых, ключевое cut слово ведет себя так же, как _ (cut), если x не является целочисленным атомом, как указано внизу этой страницы. Во-вторых, мне нужно было, чтобы сокращение начиналось с начала, поэтому я добавил к нулю, чтобы включить нулевой индекс. Взгляните на разницу между 2 4 cut til 7 и 0 2 4 cut til 7 .

3. О, понял. Вы просто добавляете 0 в начало списка, поэтому вы сокращаете, используя индексы 0 2 4 вместо индексов 2 4. Большое спасибо.