Oneliner untuk menggabungkan garis dengan bidang pertama yang sama

15

Ini adalah pertanyaan codegolf pertama saya, jadi saya minta maaf sebelumnya jika itu tidak sesuai, dan saya menyambut umpan balik.

Saya punya file dengan format ini:

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

Isi sebenarnya bervariasi, seperti halnya pembatas. Isinya hanya teks. Pembatas hanya muncul sekali per baris. Untuk teka-teki ini, jangan ragu untuk mengubah pembatas, mis. Gunakan "%" sebagai pembatas.

Output yang diinginkan:

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

Saya sudah memiliki skrip ruby ​​dan awk untuk menggabungkan ini, tetapi saya curiga mungkin saja memiliki oneliner pendek. yaitu satu-liner yang dapat digunakan bersama dengan pipa dan perintah lainnya pada baris perintah. Saya tidak bisa mengetahuinya, dan skrip saya sendiri terlalu panjang untuk hanya mengompres pada baris perintah.

Lebih disukai karakter terpendek. Input tidak harus diurutkan, tetapi kami hanya tertarik untuk menggabungkan garis berurutan dengan bidang pertama yang cocok. Ada garis tak terbatas dengan bidang pertama yang cocok. Field 1 bisa berupa apa saja, misalnya nama buah, nama yang tepat, dll.

(Saya menjalankan MacOS, jadi saya pribadi paling tertarik dengan implementasi yang berjalan di mac).


Berikut ini adalah contoh / tes kedua. Perhatikan "|" adalah pembatas. Ruang sebelum "|" tidak relevan, dan jika membenci harus dianggap bagian dari kunci. Saya menggunakan "%" sebagai pembatas dalam output, tapi sekali lagi, jangan ragu untuk mengubah pembatas (tapi jangan menggunakan tanda kurung siku).

Memasukkan:

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

Output yang diinginkan:

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
sumber
Apakah baris baru di awal output diperbolehkan?
mIllIbyte
menambahkan komentar ke pertanyaan awal. Dan, @mIllIbyte, baris baru tidak relevan bagi saya. Tetapi dalam ide saya, tidak ada garis kosong, dan tidak ada pengecekan error. Saya menganggap semua baris memiliki teks, dan setidaknya kolom pertama dan pembatas.
MichaelCodes
Menilai dari uji kasus, apakah aman untuk mengasumsikan bahwa semua kunci dikelompokkan? Yaitu: ["A|some text", "B|other text", "A|yet some other text"]bukan input yang diinginkan untuk diuji, karena kata kunci untuk Atidak satu demi satu dalam daftar.
Kevin Cruijssen
Saya menganggap semua kunci dikelompokkan. Saya tidak peduli dengan kasus di mana mereka tidak, meskipun secara teori, mereka tidak akan diperlakukan seperti kunci unik.
MichaelCodes

Jawaban:

7

Retina , 17 byte

  • 12 byte disimpan berkat @MartinEnder
  • 1 byte disimpan berkat @ jimmy23013

Mencetak dalam byte disandikan ISO 8859-1.

Menggunakan ;bukan |sebagai pemisah field input.

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

Cobalah online.

Trauma Digital
sumber
2
@ LeakyNun Karena lookaround adalah atom. Pertama kali lookaround digunakan, ia menangkap seluruh awalan garis, dan setelah itu mesin regex tidak akan mundur ke dalamnya lagi.
Martin Ender
5

V , 16 13 byte

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

Cobalah online!

Kamu berkata

Jangan ragu untuk mengubah pembatas

Jadi saya memilih |sebagai pembatas. Jika ini tidak valid, beri tahu saya dan saya akan mengubahnya.

Penjelasan:

ò                #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
sumber
1
Memberitahumu???
Erik the Outgolfer
@ ΈρικΚωνσταντόπουλος Ya? Apakah itu masalah?
DJMcMayhem
Untuk teka-teki ini, jangan ragu untuk mengubah pembatas, mis. Gunakan "%" sebagai pembatas. bukan ie
Erik the Outgolfer
2
"|" pembatas baik-baik saja.
MichaelCodes
@MichaelCodes Bisakah Anda menambahkan beberapa test case lagi sehingga kami dapat memverifikasi apakah suatu solusi diperhitungkan atau tidak?
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
Anders Kaseorg
sumber
3

SQL (PostgreSQL), 43 72 byte

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

Ini mengambil keuntungan dari fungsi agregat string_agg yang berguna di PostgreSQL. Input berasal dari tabel yang disebut Tdengan 2 kolom Adan B. Untuk memenuhi pertanyaan dengan lebih baik saya telah memasukkan perintah untuk memuat data dari file ke dalam tabel. File itu Tjuga. Saya belum menghitung tabel buat pernyataan.
Outputnya akan di-unordered, tetapi jika itu merupakan masalah maka bisa diperbaiki denganORDER BY A

SQLFiddle tidak ingin bermain untuk saya, tetapi ini adalah apa yang saya dapatkan di pengaturan saya.

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
sumber
1
Agar adil, saya sarankan menyertakan perintah COPY untuk membaca isi format file yang ditentukan dalam tabel, juga, jika tidak, Anda tidak memecahkan masalah yang sama seperti orang lain.
Jules
@ Jules Cukup adil, saya memikirkan konsensus i / o default ini ketika saya menjawab. Membaca ulang pertanyaannya meskipun saya akan mengedit jawabannya.
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,'|');}

Bekerja dengan gcc. Pembatas berubah menjadi /. Mengambil input dari stdin dan menulis output ke stdout, jadi panggil dengan redirection input./a.out <filename

Tidak Disatukan:

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
sumber
1

Pyth - 15 byte

Membuat beberapa asumsi tentang masalah, akan berubah ketika OP mengklarifikasi.

jm+Khhd-sdK.ghk

Cobalah online di sini .

Maltysen
sumber
Ini tidak berfungsi jika "kunci" adalah sebuah kata, bukan satu huruf. (OP diklarifikasi dalam komentar)
DJMcMayhem
1

Python 3 - 146 Bytes

Input adalah nama file atau path file dari file, output ke stdout. Bisa jadi jauh lebih pendek jika saya bisa mengambil input sebagai teks mentah dari baris perintah

Membawa input dari stdin dan output ke stdin. Setup dengan pemisah "|". Untuk menguji input contoh pertama, gunakan pemisah" | "

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
sumber
Tantangannya tidak secara eksplisit meminta input untuk dibaca dari file, jadi saya kira metode I / O Default kami berlaku di sini. Dan karena jawaban lain juga mengambil input dari STDIN, saya kira OP tidak masalah.
Denker
@ DenkerAffe Baiklah saya akan mengeditnya, itu hanya akan sama sekali tidak berguna karena saya tidak berpikir Anda bahkan dapat memberikan input multiline aktual dari stdin.
Keatinge
Tetapi Anda dapat melakukan pengalihan input saat menjalankan skrip.
mIllIbyte
1

Java 7, 167 byte

Mungkin bisa bermain golf lebih banyak dengan menggunakan pendekatan yang berbeda ..

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

CATATAN: Metode di atas membuat dan mengembalikan a HashMapdengan pasangan nilai kunci yang diinginkan. Namun, itu tidak mencetaknya dalam output yang tepat seperti dalam pertanyaan OP dengan |sebagai pembatas-output antara kunci dan nilai-nilai baru. Dilihat oleh jawaban SQL MickeyT di mana ia mengembalikan tabel database saya pikir ini diperbolehkan; jika tidak lebih banyak byte harus ditambahkan untuk fungsi cetak.

Tidak digabungkan & kode uji:

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

Keluaran:

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
sumber
1

PowerShell, 85 byte

String digabung menggunakan hashtable:

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

Contoh

Karena PowerShell tidak mendukung pengalihan stdin via <, saya berasumsi itu Get-Content .\Filename.txt |akan digunakan sebagai metode I / O default.

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

Keluaran

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
sumber
1

APL, 42 karakter

{⊃{∊⍺,{⍺'%'⍵}/⍵}⌸/↓[1]↑{(1,¯1↓'|'=⍵)⊂⍵}¨⍵}
lstefano
sumber
bukan satu byte dalam pengkodean APL.
Zacharý
0

Sed, 55 byte

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

Uji coba:

$ 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
Harun
sumber
0

q / kdb +, 46 byte

Larutan:

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

Contoh:

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"

Penjelasan:

`: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
sumber