Oneliner для об'єднання ліній з тим же першим полем


15

Це моє перше питання про кодегольф, тому я заздалегідь вибачаюся, якщо це не підходить, і я вітаю будь-які відгуки.

У мене файл у такому форматі:

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

Чи дозволений новий рядок на початку виводу?
mIllIbyte

додав коментарі до оригінального запитання. І, @mIllIbyte, новий рядок для мене не має значення. Але в моїй ідеї немає порожніх рядків і перевірки помилок. Я припускаю, що всі рядки мають текст, принаймні перший стовпець та роздільник.
MichaelCodes

Судячи з тестових випадків, чи врятувати можна припустити, що всі ключі згруповані? Тобто: ["A|some text", "B|other text", "A|yet some other text"]це не бажаний вхід для тестування, оскільки ключові слова для Aсписку не є один за одним.
Kevin Cruijssen

Я припускав, що всі ключі згруповані. Мене не хвилює випадок, коли їх немає, хоча теоретично це не так, щоб до них ставились як до унікальних ключів.
MichaelCodes

Відповіді:


7

Сітківка , 17 байт

  • 12 байт збережено завдяки @MartinEnder
  • 1 байт збережено завдяки @ jimmy23013

Оцінено в кодованих байтах ISO 8859-1.

Використовується ;замість цього |як розділювач поля введення.

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

Спробуйте в Інтернеті.



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)

1
Дам тобі знати???
Ерік Аутгольфер

@ ΈρικΚωνσταντόπουλος Так? Це проблема?
Джеймс

Для цієї головоломки сміливо міняйте роздільник, наприклад, використовуйте "%" як роздільник. не тобто
Ерік Аутгольфер

2
Значок "|" роздільник - це добре.
MichaelCodes

@MichaelCodes Чи можете ви додати ще кілька тестових випадків, щоб ми могли перевірити, чи є рішення чи ні?
Джеймс

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з 2 стовпцями 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

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. Розмежувач змінено на /. Приймає вхід з stdin і записує вихід у stdout, тому дзвоніть з перенаправленням вводу./a.out <filename

Безголівки:

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,'|');}


1

Пітон 3 - 146 байт

Введення - це ім'я або шлях до файлу, вихід - до stdout. Може бути набагато коротшим, якби я міг взяти введення як вихідний текст з командного рядка

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

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)))

Завдання не вимагає явного зчитування вхідного файлу з файлу, тому я думаю, що тут застосовуються наші методи вводу / виводу за замовчуванням . А оскільки інші відповіді також беруть інформацію від STDIN, я вважаю, що ОП добре з цим.
Денкер

@DenkerAffe Добре, я відредагую це, це буде просто марно, тому що я не думаю, що ви навіть можете дати фактичний багаторядковий вхід від stdin.
Кітінг

Але ви можете зробити перенаправлення вводу під час запуску сценарію.
mIllIbyte

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;}

ПРИМІТКА. Наведений вище метод створює та повертає а HashMapз потрібними парами ключ-значення. Однак він не друкує його в точному виході, як у запитанні ОП, |як роздільник виводу між клавішами та новими значеннями. Судячи з відповіді SQL Міккейна, куди він повернув таблицю бази даних, я вважав, що це дозволено; якщо для функції друку не слід додати більше байтів.

Невикористаний і тестовий код:

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


0

Сід, 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 "%"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.