Oneliner для объединения строк с одним и тем же первым полем

15

Это мой первый вопрос по Codegolf, поэтому я прошу прощения заранее, если он не подходит, и я приветствую любые отзывы.

У меня есть файл с этим форматом:

a | rest of first line
b | rest of second line
b | rest of third line
c | rest of fourth line
d | rest of fifth line
d | rest of sixth line

Фактическое содержание меняется, как и разделитель. Содержание просто текст. Разделитель появляется только один раз в строке. Для этой головоломки не стесняйтесь менять разделитель, например, используйте «%» в качестве разделителя.

Желаемый вывод:

a | rest of first line
b | rest of second line % rest of third line
c | rest of fourth line
d | rest of fifth line % rest of sixth line

У меня уже есть оба сценария ruby ​​и awk, чтобы объединить это, но я подозреваю, что возможно иметь короткий oneliner. т. е. однострочник, который можно использовать вместе с трубами и другими командами в командной строке. Я не могу понять это, и мой собственный сценарий состоит в том, чтобы долго просто сжимать в командной строке.

Самые короткие символы предпочтительнее. Входные данные не обязательно отсортированы, но нас интересует только объединение последовательных строк с соответствующими первыми полями. Есть неограниченное количество строк с соответствующими первыми полями. Поле 1 может быть любым, например, названия фруктов, собственные имена и т. Д.

(Я работаю на MacOS, поэтому лично меня больше всего интересуют реализации, которые работают на Mac).


Вот второй пример / тест. Обратите внимание "|" это разделитель. Пробел перед "|" не имеет значения, и при повторном обращении следует считать частью ключа. Я использую «%» в качестве разделителя в выводе, но опять же, не стесняйтесь менять разделитель (но не используйте квадратные скобки).

Входные данные:

why|[may express] surprise, reluctance, impatience, annoyance, indignation
whom|[used in] questions, subordination
whom|[possessive] whose
whom|[subjective] who
whoever|[objective] whomever
whoever|[possessive] whosever
who|[possessive] whose
who|[objective] whom

Желаемый вывод:

why|[may express] surprise, reluctance, impatience, annoyance, indignation
whom|[used in] questions, subordination%[possessive] whose%[subjective] who
whoever|[objective] whomever%[possessive] whosever
who|[possessive] whose%[objective] whom
MichaelCodes
источник
Разрешается ли перевод строки в начале вывода?
Миллибайт
добавил комментарии в оригинальный вопрос. И, @mIllIbyte, новая строка не имеет значения для меня. Но в моей идее нет пустых строк и нет проверки ошибок. Я предполагаю, что все строки имеют текст, и, по крайней мере, первый столбец и разделитель.
MichaelCodes
Судя по тестам, можно ли предположить, что все ключи сгруппированы? То есть: ["A|some text", "B|other text", "A|yet some other text"]не является желаемым входом для тестирования, так как ключевые слова Aне находятся в списке один за другим.
Кевин Круйссен
Я предположил, что все ключи сгруппированы. Меня не касается случай, когда их нет, хотя в теории это не относится к уникальным ключам.
MichaelCodes

Ответы:

7

Сетчатка , 17 байт

  • 12 байтов сохранено благодаря @MartinEnder
  • 1 байт сохранен благодаря @ jimmy23013

Забито в кодированных байтах ISO 8859-1.

Используется ;вместо в |качестве разделителя поля ввода.

(?<=(.+;).+)¶\1
%

Попробуйте онлайн.

Цифровая травма
источник
retina.tryitonline.net/…
монахиня
2
@LeakyNun, потому что взгляды атомные. При первом использовании lookaround он захватывает весь префикс строки, а после этого механизм регулярных выражений больше не возвращается назад.
Мартин Эндер
5

V , 16 13 байт

òí^¨á«©.*úsî±

Попробуйте онлайн!

Вы сказали

Не стесняйтесь менять разделитель

Поэтому я выбрал |в качестве разделителя. Если это неверно, дайте мне знать, и я изменю это.

Объяснение:

ò                #Recursively:
 í               #Search for the following on any line:
  ^¨á«©          #1 or more alphabetic characters at the beginning of the line
       .*        #Followed by anything
         ús      #Mark everything after this to be removed:
           î±    #A new line, then the first match again (one or more alphabetic characters)
DJMcMayhem
источник
1
Дам вам знать???
Эрик Outgolfer
@ ΈρικΚωνσταντόπουλος Да? Это проблема?
DJMcMayhem
Для этой головоломки не стесняйтесь менять разделитель, например, используйте «%» в качестве разделителя. не то есть
Эрик Outgolfer
2
"|" разделитель в порядке.
MichaelCodes
@MichaelCodes Не могли бы вы добавить еще несколько тестов, чтобы мы могли проверить, имеет ли значение решение или нет?
DJMcMayhem
3

Perl -0n, 2 + 43 = 45 байт

s/
.*\|/%/g,print for/(.*\|)((?:
\1|.)*
)/g

Демо-версия:

$ perl -0ne 's/
> .*\|/%/g,print for/(.*\|)((?:
> \1|.)*
> )/g' <<EOF
> why|[may express] surprise, reluctance, impatience, annoyance, indignation
> whom|[used in] questions, subordination
> whom|[possessive] whose
> whom|[subjective] who
> whoever|[objective] whomever
> whoever|[possessive] whosever
> who|[possessive] whose
> who|[objective] whom
> EOF
why|[may express] surprise, reluctance, impatience, annoyance, indignation
whom|[used in] questions, subordination%[possessive] whose%[subjective] who
whoever|[objective] whomever%[possessive] whosever
who|[possessive] whose%[objective] whom
Андерс Касеорг
источник
3

SQL (PostgreSQL), 43 72 байта

COPY T FROM'T'(DELIMITER'|');SELECT a,string_agg(b,'%')FROM T GROUP BY A

Это использует удобную агрегатную функцию string_agg в PostgreSQL. Ввод осуществляется из таблицы Tс двумя столбцами Aи B. Чтобы лучше соответствовать вопросу, я включил в команду загрузку данных из файла в таблицу. Файл Tтакже. Я не посчитал заявление на создание таблицы.
Вывод будет неупорядоченным, но если это проблема, ее можно исправить с помощьюORDER BY A

SQLFiddle не хотел играть за меня, но это то, что я получаю в своей настройке.

CREATE TABLE T (A VARCHAR(9),B VARCHAR(30));

COPY T FROM'T'(DELIMITER'|');SELECT a,string_agg(b,'%')FROM T GROUP BY A
a   string_agg
--- ----------------------------------------
c   rest of fourth line
b   rest of second line%rest of third line
a   rest of first line
d   rest of fifth line%rest of sixth line
MickyT
источник
1
Чтобы быть справедливым, я бы предложил включить команду COPY для чтения содержимого формата файла, указанного в таблице, в противном случае вы не решаете ту же проблему, что и все остальные.
Жюль
@Jules Достаточно справедливо, я думал об этом по умолчанию ввод-вывод, когда я ответил. Перечитывая вопрос, я отредактирую ответ.
MickyT
2

C 127 байтов

o[99],n[99],p=n;main(i){for(;gets(n);strncmp(o,n,i-p)?printf(*o?"\n%s":"%s",n),strcpy(o,n):printf(" /%s",i))i=1+strchr(n,'|');}

Работает с gcc. Изменен разделитель на /. Принимает ввод из стандартного ввода и записывает вывод в стандартный вывод, поэтому вызов с перенаправлением ввода./a.out <filename

Ungolfed:

o[99],n[99] //declare int, to save two bytes for the bounds
,p=n; //p is an int, saves one byte as opposed to applying an (int) cast to n,
//or to declaring o and n as char arrays
main(i){for(;gets(n);strncmp(o,n,i-p //an (int)n cast would be needed;
// -(n-i) does not work either,
//because pointer arithmetics scales to (int*)
)?printf(*o?"\n%s":"%s" //to avoid a newline at the beginning of output
,n),strcpy(o,n):printf(" /%s",i))i=1+strchr(n,'|');}
mIllIbyte
источник
1

Pyth - 15 байт

Делая несколько предположений о проблеме, изменится, когда ОП уточнит.

jm+Khhd-sdK.ghk

Попробуйте это онлайн здесь .

Maltysen
источник
Это не работает, если «ключ» - это слово, а не одна буква. (
Поясняется
1

Python 3 - 146 байт

Ввод - это имя файла или путь к файлу, вывод - в стандартный вывод. Мог бы быть намного короче, если бы я мог взять ввод как необработанный текст из командной строки

Принимает ввод из стандартного ввода и выводит в стандартный ввод. Настройка с разделителем "|". Для проверки ввода первого примера используйте разделитель" | "

from itertools import*
for c,b in groupby([x.split("|")for x in input().split("\n")],key=lambda x:x[0]):print(c,"|"," % ".join((a[1]for a in b)))
Keatinge
источник
Задача явно не требует, чтобы входные данные были прочитаны из файла, поэтому я предполагаю, что наши методы ввода / вывода по умолчанию применяются здесь. И так как другие ответы также принимают входные данные от STDIN, я полагаю, что с OP все в порядке.
Денкер
@DenkerAffe Хорошо, я отредактирую это, это будет просто бесполезно, потому что я не думаю, что вы даже можете дать фактический многострочный ввод из stdin.
Китинге
Но вы можете сделать перенаправление ввода при запуске сценария.
Миллибайт
1

Java 7, 167 байт

Вероятно, это может быть больше в гольф, используя другой подход ..

import java.util.*;Map c(String[]a){Map m=new HashMap();for(String s:a){String[]x=s.split("=");Object l;m.put(x[0],(l=m.get(x[0]))!=null?l+"%"+x[1]:x[1]);}return m;}

ПРИМЕЧАНИЕ. Приведенный выше метод создает и возвращает a HashMapс нужными парами ключ-значение. Тем не менее, он не печатает его в точном выводе, как в вопросе OP с |разделителем вывода между ключами и новыми значениями. Судя по SQL-ответу Микки, где он возвратил таблицу базы данных, я понял, что это разрешено; если не больше байтов должно быть добавлено для функции печати.

Ungolfed & тестовый код:

import java.util.*;

class Main{

    static Map c(String[] a){
        Map m = new HashMap();
        for(String s : a){
            String[] x = s.split("\\|");
            Object l;
            m.put(x[0], (l = m.get(x[0])) != null
                            ? l + "%" + x[1]
                            : x[1]);
        }
        return m;
    }

    public static void main(String[] a){
        Map m = c(new String[]{
            "why|[may express] surprise, reluctance, impatience, annoyance, indignation",
            "whom|[used in] questions, subordination",
            "whom|[possessive] whose",
            "whom|[subjective] who",
            "whoever|[objective] whomever",
            "whoever|[possessive] whosever",
            "who|[possessive] whose",
            "who|[objective] whom"
        });

        // Object instead of Map.EntrySet because the method returns a generic Map
        for (Object e : m.entrySet()){
            System.out.println(e.toString().replace("=", "|"));
        }
    }
}

Выход:

whoever|[objective] whomever%[possessive] whosever
whom|[used in] questions, subordination%[possessive] whose%[subjective] who
why|[may express] surprise, reluctance, impatience, annoyance, indignation
who|[possessive] whose%[objective] whom
Кевин Круйссен
источник
1

PowerShell, 85 байт

Строки объединяются с использованием хеш-таблицы:

%{$h=@{}}{$k,$v=$_-split'\|';$h.$k=($h.$k,$v|?{$_})-join'%'}{$h.Keys|%{$_+'|'+$h.$_}}

пример

Поскольку PowerShell не поддерживает перенаправление stdin через <, я предполагаю, что Get-Content .\Filename.txt |он будет использоваться как метод ввода-вывода по умолчанию.

Get-Content .\Filename.txt | %{$h=@{}}{$k,$v=$_-split'\|';$h.$k=($h.$k,$v|?{$_})-join'%'}{$h.Keys|%{$_+'|'+$h.$_}}

Выход

whoever|[objective] whomever%[possessive] whosever
why|[may express] surprise, reluctance, impatience, annoyance, indignation
whom|[used in] questions, subordination%[possessive] whose%[subjective] who
who|[possessive] whose%[objective] whom
beatcracker
источник
1

APL, 42 символа

{⊃{∊⍺,{⍺'%'⍵}/⍵}⌸/↓[1]↑{(1,¯1↓'|'=⍵)⊂⍵}¨⍵}
lstefano
источник
не один байт в кодировке APL.
Захари
0

Sed, 55 байтов

:a N;:b s/^\([^|]*\)|\([^\n]*\)\n\1|/\1|\2 %/;ta;P;D;tb

Тестовый забег :

$ echo """why|[may express] surprise, reluctance, impatience, annoyance, indignation
> whom|[used in] questions, subordination
> whom|[possessive] whose
> whom|[subjective] who
> whoever|[objective] whomever
> whoever|[possessive] whosever
> who|[possessive] whose
> who|[objective] whom""" | sed ':a N;:b s/^\([^|]*\)|\([^\n]*\)\n\1|/\1|\2 %/;ta;P;D;tb'
why|[may express] surprise, reluctance, impatience, annoyance, indignation
whom|[used in] questions, subordination %[possessive] whose %[subjective] who
whoever|[objective] whomever %[possessive] whosever
who|[possessive] whose %[objective] whom
Аарон
источник
0

q / kdb +, 46 байт

Решение:

exec"%"sv v by k from flip`k`v!("s*";"|")0:`:f

Пример:

q)exec"%"sv v by k from flip`k`v!("s*";"|")0:`:f
who    | "[possessive] whose%[objective] whom"
whoever| "[objective] whomever%[possessive] whosever"
whom   | "[used in] questions, subordination%[possessive] whose%[subjective] who"
why    | "[may express] surprise, reluctance, impatience, annoyance, indignation"

Объяснение:

`:f            // assumes the file is named 'f'
("s*";"|")0:   // read in file, assume it has two columns delimitered by pipe
flip `k`v      // convert into table with columns k (key) and v (value)
exec .. by k   // group on key
"%"sv v        // join values with "%"
streetster
источник