Konwertuj CSV na tabelę

15

Wyzwanie

Biorąc pod uwagę wejście CSV, wypisz prawidłową tabelę Unicode, używając znaków w polu.

Formatowanie

Tabela zostanie sformatowana przy użyciu następujących reguł:

  • Szerokość kolumny będzie równa najdłuższej wartości tej kolumny
  • Wszystkie dane tabeli zostaną wyjustowane
  • Każda tabela zakłada, że ​​pierwszym wierszem csv jest nagłówek
  • Tabela będzie używać następujących znaków do swoich granic:

┌ ┬ ┐ ├ ┼ ┤ └ ┴ ┘ ─ │

Przykład

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  │
└──────┴───┴──────┘

Zasady

  • Obowiązują standardowe luki
  • Możesz przesłać pełny program, funkcję lub lambda
  • Dane wejściowe mogą pochodzić z pliku, argumentu programu lub dowolnej akceptowalnej alternatywy
  • Dane wyjściowe mogą być do pliku, zwrócone lub do dowolnej akceptowalnej alternatywy
  • Dane wejściowe CSV powinny mieć taki sam format, jak w moim przykładzie.
  • Najkrótsza odpowiedź w bajtach wygrywa.

Dane wejściowe CSV powinny przyjąć następującą formę:

Header1,Header2,Header3 newline
Column1,Column2,Column3 newline
Column1,Column2,Column3 optional_newline
Shaun Wild
źródło
2
Sądzę, że są dwie podstawowe metody korzystania z definicji CSV. Jeśli interesującą częścią problemu jest wynik, możesz to uczynić tak prostym, jak „dzielenie przecinków” i nie musisz się martwić, jak cytować przecinki i jak cytować znak cudzysłowu. W przeciwnym razie możesz podać konkretną metodę analizy pliku CSV („podwójne cudzysłowy przełączają tryb, w którym przecinki są ignorowane, dwa podwójne cudzysłowy w wierszu dają dosłowne podwójne cudzysłowy” jest dość powszechny, ale w żadnym wypadku nie jedyny istniejący).
4
Err, poważny problem: nie określiłeś warunku zwycięstwa. Do czego programy mają być zoptymalizowane? Długość ( code-golf )?
1
Co najmniej pierwsze trzy linki tam definiują CSV inaczej (a co najmniej dwa twierdzą, że istnieje wiele różnych sposobów, aby to zrobić). Zakładam więc, że „CSV” musi być bardziej szczegółowo zdefiniowany, aby można go było zastosować w pytaniu (i że rozwiązania będą próbowały uniknąć rozdzielania przecinków i nie obsługiwać ucieczki, ponieważ pozwala im być krótsze).
2
Ok, zredagowałem pytanie, aby uwzględnić szczegóły dotyczące formatu CSV, którego chciałbym, aby wszyscy używali.
Shaun Wild,
1
CRLF? Poważnie? Daje to dość dużą karę dla Uniksa, gdzie CR oznacza coś innego w plikach tekstowych. Prawdopodobnie zechcesz po prostu zastąpić to „newline”, pozwalając na użycie nowego wiersza dla systemu operacyjnego.

Odpowiedzi:

10

Wypróbuj (Dyalog) APL , 38 43 bajty

Ostatni wiersz wprowadzania musi mieć końcowy znak nowej linii.

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

Wypróbuj online! W wersji offline Dyalog APL, wykonaj ]boxing ON -style=mindla tego samego efektu.

Wyjaśnienie

{ ... } anonimowa funkcja, w której reprezentuje argument:

¯1 ⌽ ⍵ obróć tylną linię nowej linii do przodu

(s ←... )zdefiniuj funkcję s następująco, i stosować go

  1 ↓¨ upuść pierwszy znak każdego z nich

  ⊢ ⊂⍨ linia, podział gdzie

  ⊃ = ⊢ pierwszy znak to znaki w ciągu

',' ,¨ następnie wstaw przecinek do każdej linii

zastosuj funkcję s do każdej linii

{ ... } zastosuj teraz następującą anonimową funkcję:

  1 ↓ ⍵ upuść pierwszy element (nagłówki wierszy)

  ↓ ⍉ ↑ transponuj listę wierszy do listy kolumn

  ↑¨ przekształć każdy element (listę wpisów) w macierz wypełnionych wpisów

  ⍉ ⍪ przekształć w macierz jednokolumnową, a następnie przetransponuj na macierz jednorzędową

  (⊃⍵) ⍪ umieść pierwszy element argumentu (listę nagłówków) na górze`

Uwaga: Chociaż znaki mojego rysowania linii nie są jawnie używane w moim rozwiązaniu, są one częścią zestawu znaków APL i będą również liczone jako pojedyncze bajty.

Adám
źródło
Patrz komentarze powyżejIs input using list or array of strings (and no newlines) valid? Nope.
edc65,
@ edc65 Naprawiono. Dzięki.
Adám
Hah, ten zapakowany wyświetlacz z pewnością się przyda :)
Ven
2

PowerShell 3+, 365 bajtów

$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'┴')┘"

Wydaje mi się, że można to znacznie poprawić, ale zabrakło mi czasu. Wszystkie zakończenia linii są \nbez \r, kodowanie to UTF8 bez BOM.

briantist
źródło
1

Rakieta 578 bajtów

(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'("└" "─" "┴" "┘")))

Nie golfowany:

(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 '("└" "─" "┴" "┘"))
    ))

Testowanie:

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

Wynik:

┌──────┬───┬──────┐
│Name  │Age│Gender│
├──────┼───┼──────┤
│Shaun │19 │Male  │
│Debra │19 │Female│
│Alan  │26 │Male  │
│George│15 │Male  │
└──────┴───┴──────┘
rnso
źródło
1

JavaScript (ES6 | FireFox), 286 bajtów

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('└┴┘'))

Wykorzystuje padEndspecyfikę FireFox.

Mwr247
źródło
1
Czy to nie 288 bajtów?
Adám
1
@ Adám ... tak ... Naprawiono
Mwr247,
Używasz tego dużo, nie jest g('└┴┘')równoważne g└┴┘(z backticks po gi na końcu)?
NoOneIsHere
1
padEndjest niestandardowy. Należy określić niezbędne środowisko wykonywania.
Neil
1
Ponadto istnieje kilka miejsc, w których piszesz `foo`+bar+`baz`- możesz zapisać bajt za pomocą szablonu `foo${bar}baz`.
Neil
1

JavaScript (ES6), 281 bajtów

Uwaga: wprowadź jako pojedynczy ciąg znaków z nowymi wierszami - zgodnie z żądaniem OP. Inne odpowiedzi używają listy ciągów - używając wejściowej tablicy ciągów mogę uniknąć pierwszego podziału i wycięcia 9 bajtów.

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

Mniej golfa

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

Test

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>

edc65
źródło
0

Python 3, 318 bajtów

-3 bajty dla użycia %formatowania i -1 dla skrótustr.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)]))

Wymaga danych wejściowych ujętych w cudzysłów.

Karl Napf
źródło
1
Wygląda mi na 318 bajtów.
Adám
1
@ Adám Masz rację, spojrzałem na znaki.
Karl Napf,
Nie działa, ponieważ input()zajmuje tylko jedną linię na każde połączenie. Będziesz musiał dzwonić, input()dopóki nie będzie więcej linii, lub czytać bezpośrednio z stdin.
movatica
Poza tym: 292 bajtów
movatica
0

C #, 696 bajtów

Gra w golfa:

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

Niegolfowany (i ładniejszy, ponieważ ^ nikomu to nie służy):

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

Testowanie:

┌──────┬───┬──────┐         ┌──────────┬───────────────────────────┬─────┐
|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  |         └──────────┴───────────────────────────┴─────┘
└──────┴───┴──────┘
Pete Arden
źródło
Jakoś ciągle otrzymuję 697 bajtów, licząc to.
Adám
@ Adám Ponownie zaznaczone, ciąg Golfed ma 666 kolumn w Visual Studio. Ale ani 666, ani 697 i tak nie są dokładnie wynikami w rywalizacji :)
Pete Arden
Masz końcowy znak nowej linii, ale nawet po jej usunięciu nadal ma on 696 bajtów .
Adám
@ Adám Ah ... Czekałem na rozbieżność liczby liter / bajtów, która mnie potknie. Powinien był wiedzieć o tych śmiesznych symbolach w tym („┼”). Zaktualizowano, dziękuję :)
Pete Arden
Patrz komentarze powyżejIs input using list or array of strings (and no newlines) valid? Nope.
edc65,
0

Perl, 273 + 9 ( -CS -nlaF,flagi) = 282 bajtów

$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];{

Za pomocą:

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

Wypróbuj na Ideone .

Denis Ibaev
źródło
0

PHP, 313 bajtów

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

awaria

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

Przetestuj to w ideone

Tytus
źródło
0

APL (Dyalog Extended) , 36 25 bajtów SBCS

Pełny program Zakłada, że ABCDEFGHIJKLMNOPQRSTUVWXYZjest to plik CSV. Drukuje na standardowe wyjście.

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

Wypróbuj online!

⎕A wielkie lphabet (najkrótsza do odniesienia wbudowanym ciąg)  odczytać ten plik i konwertować z CSV do macierzy  sklepie jako (dla m Atrix)  spadnie pierwszy wiersz  transpozycji  podzielony na liście kolumn  wymieszać każdą listę ciągów do matrycy …  Ułóż na tym następujące elementy:  weź pierwszy wiersz  zastosowania do tego (rysuje znaki rysowania linii)
⎕CSV
m←m
1↓


↑¨
()⍪
1↑mm
⌂dispdfns.disp

Adám
źródło