Oneliner do łączenia linii z tym samym pierwszym polem

15

To jest moje pierwsze pytanie o codegolf, więc z góry przepraszam, jeśli nie jest właściwe, i cieszę się z wszelkich opinii.

Mam plik w tym formacie:

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

Rzeczywista zawartość jest różna, podobnie jak separator. Treść jest tylko tekstem. Separator pojawia się tylko raz w linii. W przypadku tej układanki możesz zmienić ogranicznik, np. Użyj „%” jako ogranicznika.

Pożądane wyjście:

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

Mam już zarówno skrypty ruby, jak i awk, aby to scalić, ale podejrzewam, że można mieć krótki oneliner. tj. jednowierszowy, którego można używać wraz z potokami i innymi poleceniami w wierszu poleceń. Nie potrafię tego rozgryźć, a mój własny skrypt musi zbyt długo kompresować się w wierszu poleceń.

Preferowane najkrótsze postacie. Dane wejściowe niekoniecznie są sortowane, ale interesuje nas tylko łączenie kolejnych wierszy z dopasowywaniem pierwszych pól. Istnieje nieograniczona liczba linii z pasującymi pierwszymi polami. Pole 1 może być dowolne, np. Nazwy owoców, nazwy własne itp.

(Pracuję na MacOS, więc osobiście najbardziej interesują mnie implementacje działające na Macu).


Oto drugi przykład / test. Uwaga „|” jest ogranicznikiem. Przestrzeń przed „|” jest nieistotny i jeśli resent powinien być uważany za część klucza. Używam „%” jako ogranicznika w danych wyjściowych, ale ponownie możesz zmienić ogranicznik (ale nie używaj nawiasów kwadratowych).

Wejście:

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

Pożądane wyjście:

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
źródło
Czy dozwolona jest nowa linia na początku danych wyjściowych?
mIllIbyte
dodał komentarze do oryginalnego pytania. I @mIllIbyte, nowa linia nie ma dla mnie znaczenia. Ale w moim pomyśle nie ma pustych wierszy ani sprawdzania błędów. Zakładam, że wszystkie linie mają tekst, a przynajmniej pierwsza kolumna i separator.
MichaelCodes
Sądząc po przypadkach testowych, czy można założyć, że wszystkie klucze są zgrupowane? To ["A|some text", "B|other text", "A|yet some other text"]znaczy : nie jest pożądanym wejściem do przetestowania, ponieważ słowa kluczowe dla Anie są jeden po drugim na liście.
Kevin Cruijssen
Zakładam, że wszystkie klucze są zgrupowane. Nie interesuje mnie przypadek, w którym tak nie jest, choć teoretycznie nie byłyby traktowane jak unikalne klucze.
MichaelCodes,

Odpowiedzi:

7

Siatkówka , 17 bajtów

  • 12 bajtów zapisanych dzięki @MartinEnder
  • 1 bajt zapisany dzięki @ jimmy23013

Zapisane w bajtach zakodowanych według ISO 8859-1.

Używa ;zamiast |jako separatora pola wejściowego.

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

Wypróbuj online.

Cyfrowa trauma
źródło
2
@LeakyNun Ponieważ spojrzenia są atomowe. Przy pierwszym użyciu lookaround przechwytuje cały prefiks linii, a następnie silnik regex nie będzie już do niego wracał.
Martin Ender
5

V , 16 13 bajtów

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

Wypróbuj online!

Powiedziałeś

Zmień ogranicznik

Wybrałem więc |jako separator. Jeśli jest to nieprawidłowe, daj mi znać, a ja to zmienię.

Wyjaśnienie:

ò                #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)
James
źródło
1
Dać Ci znać???
Erik the Outgolfer
@ ΈρικΚωνσταντόπουλος Tak? Czy to problem?
James
W przypadku tej układanki możesz zmienić ogranicznik, np. Użyj „%” jako ogranicznika. nie ie
Erik the Outgolfer
2
„|” ogranicznik jest w porządku.
MichaelCodes
@MichaelCodes Czy możesz dodać więcej przypadków testowych, abyśmy mogli zweryfikować, czy rozwiązanie się liczy?
James
3

Perl -0n, 2 + 43 = 45 bajtów

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

Próbny:

$ 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
Anders Kaseorg
źródło
3

SQL (PostgreSQL), 43 72 bajty

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

Wykorzystuje to przydatną funkcję agregującą string_agg w PostgreSQL. Dane wejściowe pochodzą z tabeli o nazwie Tz 2 kolumnami Ai B. Aby lepiej dostosować się do pytania, załączyłem polecenie załadowania danych z pliku do tabeli. Plik też jest T. Nie policzyłem instrukcji tworzenia tabeli.
Wyjście będzie nieuporządkowane, ale jeśli jest to problem, można to naprawić za pomocąORDER BY A

SQLFiddle nie chciał dla mnie grać, ale to właśnie dostaję w mojej konfiguracji.

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
źródło
1
Aby być uczciwym, sugeruję włączenie polecenia COPY do odczytu zawartości formatu pliku określonego w tabeli, w przeciwnym razie nie rozwiążesz tego samego problemu, co wszyscy inni.
Jules
@Jules W porządku, myślałem o tym domyślnym concensus we / wy, kiedy odpowiedziałem. Przeszukując pytanie, zmienię odpowiedź.
MickyT,
2

C, 127 bajtów

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

Działa z gcc. Zmieniono separator na/ . Pobiera dane wejściowe ze standardowego wejścia i zapisuje dane wyjściowe na standardowe wyjście, więc wywołaj z przekierowaniem wejściowym./a.out <filename

Nie golfowany:

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,'|');}
Mllllbyte
źródło
1

Pyth - 15 bajtów

Przyjmując kilka założeń dotyczących problemu, zmieni się, gdy PO wyjaśni.

jm+Khhd-sdK.ghk

Wypróbuj online tutaj .

Maltysen
źródło
To nie działa, jeśli „klucz” jest słowem, a nie pojedynczą literą. (OP wyjaśnione w komentarzach)
James
1

Python 3 - 146 bajtów

Wejście to nazwa pliku lub ścieżka pliku, wyjście to standardowe wyjście. Mógłbym być znacznie krótszy, gdybym mógł pobierać dane jako surowy tekst z wiersza poleceń

Pobiera dane wejściowe ze standardowego wejścia i wyjścia na standardowe wyjście. Konfiguracja z separatorem "|". Aby przetestować pierwsze przykładowe wejście, użyj separatora" | "

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
źródło
Wyzwanie nie wymaga jawnego odczytu danych wejściowych z pliku, więc chyba tutaj obowiązują nasze domyślne metody we / wy . A ponieważ inne odpowiedzi również biorą wkład ze STDIN, przypuszczam, że OP jest w porządku.
Denker
@DenkerAffe W porządku, wyedytuję to, będzie to po prostu całkowicie bezużyteczne, ponieważ nie sądzę, abyś mógł nawet podać rzeczywiste wejście multilinii ze standardowego wejścia.
Keatinge
Ale możesz uruchomić przekierowanie wejściowe po uruchomieniu skryptu.
mIllIbyte
1

Java 7, 167 bajtów

Prawdopodobnie można go bardziej zagrać w golfa, stosując inne podejście ...

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

UWAGA: Powyższa metoda tworzy i zwraca a HashMapz pożądanymi parami klucz-wartość. Jednak nie drukuje go w dokładnym wyniku, jak w pytaniu OP z |ogranicznikiem wyjścia między kluczami a nowymi wartościami. Sądząc po odpowiedzi SQL MickeyT, w której zwrócił tabelę bazy danych, pomyślałem, że jest to dozwolone; jeśli nie, należy dodać więcej bajtów dla funkcji drukowania.

Kod niepoznany i testowy:

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("=", "|"));
        }
    }
}

Wynik:

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
Kevin Cruijssen
źródło
1

PowerShell, 85 bajtów

Ciągi są scalane przy użyciu tablicy hashtable:

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

Przykład

Ponieważ PowerShell nie obsługuje przekierowania standardowego przez <, zakładam, że Get-Content .\Filename.txt |będzie on używany jako domyślna metoda we / wy.

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

Wynik

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
źródło
1

APL, 42 znaki

{⊃{∊⍺,{⍺'%'⍵}/⍵}⌸/↓[1]↑{(1,¯1↓'|'=⍵)⊂⍵}¨⍵}
lstefano
źródło
nie jest jednym bajtem w kodowaniu APL.
Zacharý
0

Sed, 55 bajtów

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

Testowe uruchomienie :

$ 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
Aaron
źródło
0

q / kdb +, 46 bajtów

Rozwiązanie:

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

Przykład:

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"

Wyjaśnienie:

`: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
źródło