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

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.



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)

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

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

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

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 .


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

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

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

1

APL, 42 znaki

{⊃{∊⍺,{⍺'%'⍵}/⍵}⌸/↓[1]↑{(1,¯1↓'|'=⍵)⊂⍵}¨⍵}

⌸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

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 "%"
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.