Oneliner per unire le linee con lo stesso primo campo


15

Questa è la mia prima domanda su codegolf, quindi mi scuso in anticipo se non è appropriato e accolgo con favore qualsiasi feedback.

Ho un file con questo formato:

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

I contenuti effettivi variano, così come il delimitatore. I contenuti sono solo testo. Il delimitatore appare solo una volta per riga. Per questo puzzle, sentiti libero di cambiare il delimitatore, ad esempio usa "%" come delimitatore.

Uscita desiderata:

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

Ho già entrambi gli script Ruby e Awk per unire questo, ma sospetto che sia possibile avere un breve line-up. vale a dire un one-liner che può essere utilizzato insieme a tubi e altri comandi sulla riga di comando. Non riesco a capirlo, e il mio script è troppo lungo da comprimere solo dalla riga di comando.

Personaggi più corti preferiti. L'input non è necessariamente ordinato, ma siamo interessati solo a unire le righe consecutive con i primi campi corrispondenti. Esistono linee illimitate con i primi campi corrispondenti. Il campo 1 potrebbe essere qualsiasi cosa, ad esempio nomi di frutti, nomi propri, ecc.

(Corro su MacOS, quindi sono personalmente più interessato alle implementazioni che girano su Mac).


Ecco un secondo esempio / test. Avviso "|" è il delimitatore. Lo spazio prima del "|" è irrilevante e se il rinvio deve essere considerato parte della chiave. Sto usando "%" come delimitato nell'output, ma di nuovo, mi sento libero di cambiare il delimitatore (ma non uso parentesi quadre).

Ingresso:

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

Uscita desiderata:

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

È consentita una nuova riga all'inizio dell'output?
— mIllIbyte,

aggiunti commenti alla domanda originale. E, @mIllIbyte, una nuova riga è irrilevante per me. Ma nella mia idea, non ci sono righe vuote e nessun controllo degli errori. Presumo che tutte le righe abbiano testo e almeno la prima colonna e il delimitatore.
— MichaelCodes

A giudicare dai casi di test, è salvo supporre che tutte le chiavi siano raggruppate? Vale a dire: ["A|some text", "B|other text", "A|yet some other text"]non è un input desiderato da testare, poiché le parole chiave per Anon sono una dopo l'altra nell'elenco.
— Kevin Cruijssen,

Presumo che tutte le chiavi siano raggruppate. Non mi preoccupo del caso in cui non lo sono, anche se in teoria non verrebbero trattati come chiavi uniche.
— MichaelCodes

Risposte:


7

Retina , 17 byte

  • 12 byte salvati grazie a @MartinEnder
  • 1 byte salvato grazie a @ jimmy23013

Segnati in byte codificati ISO 8859-1.

Utilizza ;invece |come separatore del campo di input.

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

Provalo online.



2
@LeakyNun Perché i lookaround sono atomici. La prima volta che viene utilizzato il lookaround, acquisisce l'intero prefisso della linea e, successivamente, il motore regex non tornerà più indietro.
— Martin Ender,

5

V , 16 13 byte

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

Provalo online!

Tu hai detto

Sentiti libero di cambiare il delimitatore

Quindi ho scelto |come delimitatore. Se questo non è valido, fammi sapere e lo cambierò.

Spiegazione:

ò                #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
Farti sapere???
— Erik the Outgolfer,

@ ΈρικΚωνσταντόπουλος Sì? È un problema?
— DJMcMayhem

Per questo puzzle, sentiti libero di cambiare il delimitatore, ad esempio usa "%" come delimitatore. non vale a dire
— Erik the Outgolfer,

2
Il "|" il delimitatore va bene.
— MichaelCodes

@MichaelCodes Potresti aggiungere altri casi di test in modo da poter verificare se una soluzione conta o no?
— DJMcMayhem

3

Perl -0n, 2 + 43 = 45 byte

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

demo:

$ 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 byte

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

Questo sfrutta la pratica funzione aggregata string_agg in PostgreSQL. L'input proviene da una tabella chiamata Tcon 2 colonne Ae B. Per soddisfare meglio la domanda, ho incluso il comando di caricare i dati da un file nella tabella. Anche il file è T. Non ho conteggiato la dichiarazione di creazione della tabella.
L'output sarà non ordinato, ma se questo è un problema può essere risolto con unORDER BY A

SQLFiddle non voleva giocare per me, ma questo è ciò che ottengo nella mia configurazione.

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
Ad essere sinceri, suggerirei di includere un comando COPY per leggere anche il contenuto del formato file specificato nella tabella, altrimenti non risolverai lo stesso problema di tutti gli altri.
— Jules,

@Jules Abbastanza giusto, stavo pensando a questo consenso i / o predefinito quando ho risposto. Rileggendo la domanda, modificherò la risposta.
— MickyT

2

C, 127 byte

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

Funziona con gcc. Delimitatore modificato in /. Prende l'input da stdin e scrive l'output su stdout, quindi chiama con reindirizzamento dell'input./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,'|');}

1

Pyth - 15 byte

Fare alcune ipotesi sul problema cambierà quando chiarirà l'OP.

jm+Khhd-sdK.ghk

Provalo online qui .


Questo non funziona se la "chiave" è una parola, piuttosto che una singola lettera. (OP chiarito nei commenti)
— DJMcMayhem

1

Python 3 - 146 byte

L'input è il nome file o il percorso del file, l'output è stdout. Potrebbe essere molto più breve se potessi prendere l'input come testo non elaborato dalla riga di comando

Prende input da stdin e output in stdin. Installazione con separatore "|". Per testare il primo esempio di input utilizzare il separatore" | "

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

La sfida non richiede esplicitamente che l'input sia letto da un file, quindi immagino che i nostri metodi I / O predefiniti si applichino qui. E poiché anche altre risposte prendono l'input da STDIN, suppongo che l'OP vada bene con esso.
— Denker,

@DenkerAffe Va bene lo modificherò, sarà completamente inutile perché non penso che tu possa anche dare un vero input multilinea da stdin.
— Keatinge,

Ma puoi eseguire il reindirizzamento dell'input quando esegui lo script.
— mIllIbyte

1

Java 7, 167 byte

Probabilmente si può giocare a golf di più usando un approccio diverso.

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

NOTA: il metodo sopra crea e restituisce un HashMapcon le coppie chiave-valore desiderate. Tuttavia, non lo stampa nell'output esatto come nella domanda di OP con |come delimitatore di output tra le chiavi e i nuovi valori. A giudicare dalla risposta SQL di MickeyT dove ha restituito una tabella di database, ho pensato che fosse consentito; se non è necessario aggiungere più byte per una funzione di stampa.

Codice non testato e test:

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

Produzione:

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 byte

Le stringhe vengono unite usando la tabella hash:

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

Esempio

Poiché PowerShell non supporta il reindirizzamento stdin tramite <, suppongo che Get-Content .\Filename.txt |verrà utilizzato come metodo I / O predefinito.

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

Produzione

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 caratteri

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

⌸non è un byte nella codifica APL.
— Zacharý,

0

Sed, 55 byte

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

Prova :

$ 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 byte

Soluzione:

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

Esempio:

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"

Spiegazione:

`: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 "%"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.