Konversi CSV ke Tabel


15

Tantangan

Diberikan input CSV, output tabel unicode yang tepat menggunakan karakter kotak.

Memformat

Tabel akan diformat menggunakan aturan berikut:

  • Lebar kolom akan sama dengan nilai terpanjang dari kolom itu
  • Semua data tabel akan dibenarkan
  • Setiap tabel akan menganggap baris csv pertama sebagai header
  • Tabel akan menggunakan karakter berikut untuk perbatasannya:

┌ ┬ ┐ ├ ┼ ┤ └ ┴ ┘ ─ │

Contoh

Input:
Name,Age,Gender
Shaun,19,Male
Debra,19,Female
Alan,26,Male
George,15,Male

Output:
┌──────┬───┬──────┐
│Name  │Age│Gender│
├──────┼───┼──────┤
│Shaun │19 │Male  │
│Debra │19 │Female│
│Alan  │26 │Male  │
│George│15 │Male  │
└──────┴───┴──────┘

Aturan

  • Celah standar berlaku
  • Anda dapat mengirimkan program lengkap, fungsi, atau lambda
  • Input dapat dari file, argumen program atau alternatif apa pun yang dapat diterima
  • Output dapat berupa file, dikembalikan atau alternatif apa pun yang dapat diterima
  • Input CSV harus menggunakan format yang sama seperti yang digunakan dalam contoh saya.
  • Jawaban terpendek dalam byte menang.

Input CSV harus berupa:

Header1,Header2,Header3 newline
Column1,Column2,Column3 newline
Column1,Column2,Column3 optional_newline

2
Saya pikir pada dasarnya ada dua cara Anda bisa pergi dengan definisi CSV. Jika bagian yang menarik dari masalahnya adalah output, Anda dapat membuatnya sesederhana "split on koma" dan tidak perlu khawatir tentang cara mengutip koma dan cara mengutip karakter kutipan. Jika tidak, Anda dapat menyatakan metode spesifik untuk menguraikan CSV ("tanda kutip ganda mengubah mode di mana koma diabaikan, dua tanda kutip ganda berturut-turut menghasilkan tanda kutip ganda literal" adalah yang cukup umum, tetapi tidak berarti satu-satunya ada).

4
Kesalahan, masalah serius: Anda belum menentukan kondisi kemenangan. Untuk apa program dioptimalkan? Panjang ( kode-golf )?

1
Setidaknya tiga tautan pertama semuanya mendefinisikan CSV secara berbeda (dan setidaknya dua mengatakan bahwa ada banyak cara berbeda untuk melakukannya). Jadi saya berasumsi bahwa "CSV" perlu lebih sepenuhnya ditentukan untuk digunakan dalam pertanyaan (dan bahwa solusi akan mencoba untuk lolos dengan pemisahan pada koma dan tidak menangani pelolosan karena memungkinkan mereka menjadi lebih pendek).

2
Oke saya sudah mengedit pertanyaan untuk memasukkan spesifik tentang format CSV yang saya ingin semua orang gunakan.
Shaun Wild

1
CRLF? Serius? Itu akan memberikan penalti yang cukup besar pada Unix, di mana CR berarti sesuatu yang lain dalam file teks. Anda mungkin ingin menggantinya dengan "baris baru", yang memungkinkan baris khusus OS untuk digunakan.

Jawaban:


10

Coba (Dyalog) APL , 38 43 byte

Baris input terakhir harus memiliki baris tambahan.

{{(⊃⍵)⍪⍉⍪↑¨↓⍉↑1↓⍵}s¨',',¨(s1↓¨⊢⊂⍨⊢=⊃)¯1⌽⍵}

Cobalah online! Dalam versi offline Dyalog APL, jalankan ]boxing ON -style=minuntuk efek yang sama.

Penjelasan

{... }fungsi anonim yang mewakili argumen:

¯1 ⌽ ⍵ putar baris baru yang tertinggal ke depan

(s ←... )tentukan fungsi s sebagai berikut, dan terapkan

  1 ↓¨ drop karakter pertama masing-masing

  ⊢ ⊂⍨ baris, bagi di mana

  ⊃ = ⊢ karakter pertama sama dengan karakter dalam string

',' ,¨ lalu tambahkan koma ke setiap baris

terapkan fungsi s untuk setiap baris

{... }sekarang terapkan fungsi anonim berikut:

  1 ↓ ⍵ drop elemen pertama (header baris)

  ↓ ⍉ ↑ transposkan daftar baris ke dalam daftar kolom

  ↑¨ buat setiap elemen (daftar entri) menjadi matriks entri yang diisi

  ⍉ ⍪ buat menjadi matriks satu kolom, lalu transposkan menjadi matriks satu baris

  (⊃⍵) ⍪ letakkan elemen pertama argumen (daftar header) di atas`

Catatan: Meskipun karakter gambar garis tidak secara eksplisit digunakan dalam solusi saya, mereka adalah bagian dari rangkaian karakter APL, dan juga akan dihitung sebagai byte tunggal.


Lihat komentar di atas Is input using list or array of strings (and no newlines) valid? Nope.
edc65

@ edc65 Diperbaiki. Terima kasih.
Adám

Hah, tampilan kotak itu sangat berguna :)
Ven

2

PowerShell 3+, 365 byte

$d=$input|ipcsv
$h=$d[0].PSObject.Properties.Name|%{$_|Add-Member -type NoteProperty -na c -v(($d.$_+$_|measure Length -ma).Maximum)-pa}
"┌$(($h|%{'─'*$_.c})-join'┬')┐"
"│$(($h|%{$_.PadRight($_.c)})-join'│')│"
"├$(($h|%{'─'*$_.c})-join'┼')┤"
$d|%{$i=$_;"│$(($h|%{$i.$_.PadRight($_.c)})-join'│')│"}
"└$(($h|%{'─'*$_.c})-join'┴')┘"

Saya merasa ini bisa banyak diperbaiki tetapi saya kehabisan waktu. Semua akhir baris \ntanpa \r, pengkodean adalah UTF8 tanpa BOM.


1

Racket 578 byte

(let*((ll(map(λ(x)(string-split x","))ll))(lr list-ref)(sl string-length)(d display)(dl displayln)(nc(length(lr ll 0)))
(nl(for/list((i nc))(apply max(for/list((j ll))(sl(lr j i))))))(pl(λ(sy)(d(lr sy 0))(for((n nc))(for((m(lr nl n)))(d(lr sy 1)))
(if(< n(sub1 nc))(d(lr sy 2))(dl(lr sy 3))))))(g(λ(i n)(for((m(-(lr nl n)(sl i))))(d" ")))))(pl'("┌""─""┬""┐"))
(for((i(lr ll 0))(n(in-naturals)))(d"│")(d i)(g i n))(dl"│")(pl'("├""─""┼""┤"))(for((j(range 1(length ll))))
(for((i(lr ll j))(n nc))(d"│")(d i)(g i n))(dl"│"))(pl'("└" "─" "┴" "┘")))

Tidak Disatukan:

(define(f1 ll)
 (let* ((ll (map (λ (x)(string-split x ",")) ll))  ; use this to convert csv format to list of lists; 
         (lr list-ref)                    ; make short names of standard fns
         (sl string-length)
         (d display)
         (dl displayln)
         (nc (length (lr ll 0)))          ; number of cols; 
         (nl(for/list ((i nc))            ; get list of max string-length for each column
              (apply max
                     (for/list ((j ll))
                       (sl (lr j i))
                       ))))
         (pl (λ (sy)                      ; put lines using sent symbol list
               (d (lr sy 0)) 
               (for ((n nc))
                 (for ((m (lr nl n))) (d (lr sy 1)))
                 (if (< n (sub1 nc))
                     (d (lr sy 2))
                     (dl (lr sy 3))
                     ))))
         (g (λ (i n)                     ; pad with spaces if needed
              (for ((m (- (lr nl n) (sl i)))) (d " ")) ))) 
    ; put line above header: 
    (pl '("┌" "─" "┬" "┐"))

    ; put header: 
    (for ((i (lr ll 0)) (n (in-naturals)))
      (d "│")
      (d i)
      (g i n)
      )
    (dl "│")

    ; put line below header;
    (pl '("├" "─" "┼" "┤"))

    ; put rows: 
    (for ((j (range 1 (length ll))))
      (for ((i (lr ll j))
            (n nc))
        (d "│")
        (d i)
        (g i n)
        )
      (dl "│")
      )

    ; put bottom line: 
    (pl '("└" "─" "┴" "┘"))
    ))

Pengujian:

(f (list  "Name,Age,Gender"
          "Shaun,19,Male"
          "Debra,19,Female"
          "Alan,26,Male"
          "George,15,Male"))

Keluaran:

┌──────┬───┬──────┐
│Name  │Age│Gender│
├──────┼───┼──────┤
│Shaun │19 │Male  │
│Debra │19 │Female│
│Alan  │26 │Male  │
│George│15 │Male  │
└──────┴───┴──────┘

1

JavaScript (ES6 | FireFox), 286 byte

f=>(d=f.split`
`.map(a=>a.split`,`),s=d[0].map((a,i)=>d.reduce((b,c)=>(n=c[i].length)>b?n:b,0)),d=d.map(a=>`│${a.map((b,i)=>b.padEnd(s[i])).join`│`}│`),d.splice(1,0,(g=h=>h[0]+s.map(a=>'─'.repeat(a)).join(h[1])+h[2])('├┼┤')),g('┌┬┐')+`
${d.join`
`}
`+g('└┴┘'))

Penggunaan padEnd, yang khusus untuk FireFox.


1
Bukankah ini 288 byte?
Adám

1
@ Adám ... ya ... Diperbaiki
Mwr247

Anda menggunakan banyak ini, tidak g('└┴┘')setara dengan g└┴┘(dengan backticks setelah gdan di akhir)?
NoOneIsHere

1
padEndtidak standar. Anda harus menentukan lingkungan eksekusi yang diperlukan.
Neil

1
Juga, ada beberapa tempat di mana Anda menulis `foo`+bar+`baz`- Anda dapat menyimpan byte dengan menggunakan templat `foo${bar}baz`.
Neil

1

JavaScript (ES6), 281 byte

Catatan: input sebagai string tunggal dengan baris baru - seperti yang diminta oleh OP. Jawaban lain menggunakan daftar string - menggunakan array string dalam input, saya dapat menghindari split pertama dan memotong 9 byte.

l=>(l=l.split`
`.map(r=>r.split`,`.map((w,i)=>(v=w.length)<c[i]?w:(c[i]=v,w)),c=[k=0]),l=l.map(r=>r.map((v,i)=>(v+' '.repeat(c[i]-v.length)))),[h=c.map(x=>'─'.repeat(x)),l.shift(),h,...l,h].map(a=>'│┌├└'[j=a!=h?0:++k]+a.join('│┬┼┴'[j])+'│┐┤┘'[j]).join`
`)

Kurang golf

l=>(
  // split input in an array of string arrays
  // meanwhile find the column widths and put them in *c*
  l = l.split`\n`.map(r=>r.split`,`.map((w,i)=>(v=w.length)<c[i]?w:(c[i]=v,w)),c=[]),

  // pad each column to the max column width
  l = l.map(r=>r.map((v,i)=>(v+' '.repeat(c[i]-v.length)))),

  // put in *h* the horizontal lines for top,bottom and head separator
  h = c.map(x => '─'.repeat(x) ),

  // add the *h* line at top, bottom and after head line
  l = [h, l.shift(), h, ...l, h],

  // rebuild a string, joining columns with '|' unless the row is *h*
  // if the row is *h* use different characters to join columns
  k = 0, 
  l.map(a=> '│┌├└'[j=a!=h?0:++k] + a.join('│┬┼┴'[j]) + '│┐┤┘'[j])
  .join`\n`  
)

Uji

F=
l=>(l=l.split`
`.map(r=>r.split`,`.map((w,i)=>(v=w.length)<c[i]?w:(c[i]=v,w)),c=[k=0]),l=l.map(r=>r.map((v,i)=>(v+' '.repeat(c[i]-v.length)))),[h=c.map(x=>'─'.repeat(x)),l.shift(),h,...l,h].map(a=>'│┌├└'[j=a!=h?0:++k]+a.join('│┬┼┴'[j])+'│┐┤┘'[j]).join`
`) 
  
function update() {
  O.textContent = F(I.value)
}
update()
#I { width:60%; height: 8em} 
<textarea id=I>Name,Age,Gender
Shaun,19,Male
Debra,19,Female
Alan,26,Male
George,15,Male</textarea><br>
<button onclick='update()'>Go</button>
<pre id=O></pre>


0

Python 3, 318 byte

-3 byte untuk menggunakan %format dan -1 untuk menyingkatstr.join

L=[c.split(',')for c in input().split('\n')]
m=[max(len(x)for x in c)for c in zip(*L)]
L=[[""]+[d.ljust(n)for d,n in zip(c,m)]+[""]for c in L]
g=["─"*i for i in m]
J=str.join
print('\n'.join(["┌%s┐"%J("┬",g),J("│",L[0]),"├%s┤"%J("┼",g)]+[J("│",L[i])for i in range(1,len(L))]+["└%s┘"%J("┴",g)]))

Membutuhkan input yang dilampirkan dalam tanda kutip.


1
Sepertinya 318 byte bagi saya.
Adám

1
@ Adám Anda benar, saya melihat karakternya.
Karl Napf

Tidak berfungsi, karena input()hanya mengambil satu jalur pada setiap panggilan. Anda harus menelepon input()sampai tidak ada lagi saluran, atau membaca langsung dari stdin.
movatica

Selain itu: 292 byte
movatica

0

C #, 696 Bytes

Golf:

string T(string[]f){int w=f.Max(r=>r.Length),a=f.Select(r=>r.Split(',')[0].Length).Max(),b=f.Select(r=>r.Split(',')[1].Length).Max(),c=f.Select(r=>r.Split(',')[2].Length).Max();string o="",n="\r\n",d="",j=string.Concat(Enumerable.Repeat("─",a)),k=string.Concat(Enumerable.Repeat("─",b)),l=string.Concat(Enumerable.Repeat("─",c));Func<string,int,string>z=(q,p)=>{return q.PadRight(p);};d="┌"+j+"┬"+k+"┬"+l+"┐";o+=d+n;var g=f.First().Split(',');o+="|"+z(g[0],a)+"|"+z(g[1],b)+"|"+z(g[2],c)+"|";d="├"+j+"┼"+k+"┼"+l+"┤";o+=n+d+n;for(int i=1;i<f.Length;i++){var h=f[i].Split(',');o+="|"+z(h[0],a)+"|"+z(h[1],b)+"|"+z(h[2],c)+"|"+n;}d="└"+j+"┴"+k+"┴"+l+"┘";o+=d;return o;}

Tidak digabungkan (dan lebih bagus, karena ^ itu tidak berguna bagi siapa pun):

public string T(string[] c)
{
  int width = c.Max(r => r.Length),
    longestFirstColumn = c.Select(r => r.Split(',')[0].Length).Max(),
    longestSecondColumn = c.Select(r => r.Split(',')[1].Length).Max(),
    longestThirdColumn = c.Select(r => r.Split(',')[2].Length).Max();

  string o = "", lr = "\r\n", border = "",
    firstColumnFiller = string.Concat(Enumerable.Repeat("─", longestFirstColumn)),
    secondColumnFiller = string.Concat(Enumerable.Repeat("─", longestSecondColumn)),
    thirdColumnFiller = string.Concat(Enumerable.Repeat("─", longestThirdColumn));

  Func<string, int, string> padRight = (a, b) => { return a.PadRight(b); };

  border = "┌" + firstColumnFiller
    + "┬" +
    secondColumnFiller + "┬"
    + thirdColumnFiller
    + "┐";

  o += border + lr;

  var firstRow = c.First().Split(',');

  o += "|" + padRight(firstRow[0], longestFirstColumn) +
    "|" + padRight(firstRow[1], longestSecondColumn) +
    "|" + padRight(firstRow[2], longestThirdColumn) + "|";

  border = "├" +
    firstColumnFiller + "┼" +
    secondColumnFiller + "┼" +
    thirdColumnFiller
    + "┤";

  o += lr + border + lr;

  for (int i = 1; i < c.Length; i++)
  {
    var row = c[i].Split(',');

    o += "|" + padRight(row[0], longestFirstColumn) + "|"
    + padRight(row[1], longestSecondColumn) + "|" +
    padRight(row[2], longestThirdColumn) + "|" + lr;
  }

  border = "└" +
    firstColumnFiller + "┴" +
    secondColumnFiller + "┴" +
    thirdColumnFiller
    + "┘";

  o += border;

  return o;
}

Pengujian:

┌──────┬───┬──────┐         ┌──────────┬───────────────────────────┬─────┐
|Name  |Age|Gender|         |Name      |PPCG Challenge             |Votes|
├──────┼───┼──────┤         ├──────────┼───────────────────────────┼─────┤
|Shaun |19 |Male  |         |Pete Arden| Print all integers        | 4   |
|Debra |19 |Female|         |Pete Arden| Yes of course I'm an adult| 3   |
|Alan  |26 |Male  |         |Pete Arden| 5 Favorite Letters        | 1   |
|George|15 |Male  |         └──────────┴───────────────────────────┴─────┘
└──────┴───┴──────┘

Entah bagaimana, saya terus mendapatkan 697 byte saat menghitung ini.
Adám

@ Adám Baru diperiksa lagi, string Golfed sepanjang 666 kolom di Visual Studio. Tapi bagaimanapun, baik 666 maupun 697 bukanlah nilai kompetitif yang sebenarnya :)
Pete Arden

Anda memiliki trailing baris baru, tetapi bahkan ketika menghapusnya, itu masih 696 byte .
Adám

@ Adám Ah ... Saya sudah menunggu perbedaan huruf hitung / byte untuk membuat saya tersandung. Seharusnya tahu dengan simbol-simbol lucu ini ("┼"). Diperbarui, terima kasih :)
Pete Arden

Lihat komentar di atasIs input using list or array of strings (and no newlines) valid? Nope.
edc65

0

Perl, 273 + 9 ( -CS -nlaF,bendera) = 282 byte

$v[$.-1]=[@F];map$l[$_]<($l=length$F[$_])&&($l[$_]=$l),0..$#F}sub p{printf$p,@_}sub o{p
pop,map{$\x$l[$_],$_-$#l?$_[0]:pop}0..$#l}$p=join'%s','',(map"\%-${_}s",@l),$/;($\,$c,@c)=map
chr$_*4+9472,0,.5,3..15;o@c[8,1,0];p($c,map{$_,$c}@$_),$i++||o@c[12,6,4]for@v;o@c[10,3,2];{

Menggunakan:

cat file.csv | perl -CS -nlaF, script.pl

Cobalah di Ideone .


0

PHP, 313 byte

for(;$r=fgetcsv(STDIN);$a[]=$r)foreach($r as$x=>$s)$e[$x]=max($e[$x],strlen($s));$t=["┬","┌","┐"];eval($L='foreach($e as$i=>$n)echo$t[!$i],str_repeat("─",$n);echo"$t[2]\n";');foreach($a as$k=>$r){foreach($r as$i=>$s)echo"│",str_pad($s,$e[$i]);echo"│\n";$t=["┼","├","┤"];if(!$k)eval($L);}$t=["┴","└","┘"];eval($L);

kerusakan

for(;$r=fgetcsv(STDIN);$a[]=$r)                         // read csv from STDIN, append to array $a
    foreach($r as$x=>$s)$e[$x]=max($e[$x],strlen($s));  // remember max length in array $e
                                                        // print top border
$t=["┬","┌","┐"];eval($L='foreach($e as$i=>$n)echo$t[!$i],str_repeat("─",$n);echo"$t[2]\n";');
foreach($a as$k=>$r)
{
    foreach($r as$i=>$s)echo"│",str_pad($s,$e[$i]);echo"│\n";   // print row
    $t=["┼","├","┤"];if(!$k)eval($L);                           // print border below header
}
$t=["┴","└","┘"];eval($L);                              // print bottom border

Uji di ideone


0

APL (Dyalog Extended) , 36 25 byte SBCS

Program lengkap. Diasumsikan itu ABCDEFGHIJKLMNOPQRSTUVWXYZadalah file CSV. Mencetak ke stdout.

disp(1m)⍪↑¨↓⍉1m←⎕CSVA

Cobalah online!

⎕A huruf besar A lphabet (terpendek-to-referensi built-in string)
⎕CSV membaca file dan mengkonversi dari CSV ke matriks
m← toko sebagai m(untuk m atrix)
1↓ menjatuhkan baris pertama
 transpose
 dibagi menjadi daftar kolom
↑¨ campuran masing-masing daftar string menjadi matriks
(... )⍪ susun berikut di atas itu:
1↑m ambil baris pertama dari m
⌂disp berlaku dfns.dispuntuk itu (menggambar karakter menggambar garis)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.