Konvertieren Sie CSV in Tabelle


15

Die Herausforderung

Geben Sie bei einer CSV-Eingabe eine richtige Unicode-Tabelle mit Box-Zeichen aus.

Formatierung

Die Tabelle wird nach folgenden Regeln formatiert:

  • Die Spaltenbreite entspricht dem längsten Wert dieser Spalte
  • Alle Tabellendaten bleiben in der richtigen Reihenfolge
  • Jede Tabelle nimmt an, dass die erste csv-Zeile der Header ist
  • In der Tabelle werden die folgenden Zeichen als Rahmen verwendet:

┌ ┬ ┐ ├ ┼ ┤ └ ┴ ┘ ─ │

Beispiel

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

Regeln

  • Es gelten Standardlücken
  • Sie können ein vollständiges Programm, eine Funktion oder ein Lambda einreichen
  • Die Eingabe kann aus einer Datei, einem Programmargument oder einer beliebigen akzeptablen Alternative erfolgen
  • Die Ausgabe kann in einer Datei, als Rückgabe oder in einer beliebigen akzeptablen Alternative erfolgen
  • Die CSV-Eingabe sollte dasselbe Format wie in meinem Beispiel haben.
  • Kürzeste Antwort in Bytes gewinnt.

CSV-Eingaben sollten die folgende Form haben:

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

2
Ich denke, es gibt grundsätzlich zwei Möglichkeiten, wie Sie mit der CSV-Definition vorgehen können. Wenn der interessante Teil des Problems die Ausgabe ist, können Sie es so einfach wie "Nach Kommas teilen" gestalten und müssen sich keine Gedanken darüber machen, wie Kommas und das Anführungszeichen zu zitieren sind. Andernfalls können Sie eine bestimmte Methode zum Parsen der CSV angeben ("Doppelte Anführungszeichen schalten einen Modus um, in dem Kommas ignoriert werden, zwei doppelte Anführungszeichen in einer Reihe ergeben ein wörtliches doppeltes Anführungszeichen"). Dies ist jedoch keineswegs die einzige Methode besteht).

4
Äh, ernstes Problem: Sie haben keine Siegbedingung angegeben. Wofür sollen die Programme optimiert werden? Länge ( Code-Golf )?

1
Mindestens die ersten drei Links definieren CSV unterschiedlich (und mindestens zwei sagen, dass es viele verschiedene Möglichkeiten gibt, dies zu tun). Daher gehe ich davon aus, dass "CSV" für die Verwendung in einer Frage vollständiger definiert werden muss (und dass die Lösungen versuchen werden, mit Kommasplittung und nicht mit Escape-Zeichen auszukommen, da sie kürzer sein können).

2
Okay, ich habe die Frage so bearbeitet, dass sie Einzelheiten zum CSV-Format enthält, das jeder verwenden soll.
Shaun Wild

1
CRLF? Ernsthaft? Das wird für Unix eine ziemlich große Strafe bedeuten, da CR in Textdateien etwas anderes bedeutet. Sie möchten das wahrscheinlich einfach durch "newline" ersetzen, damit die betriebssystemspezifische newline verwendet werden kann.

Antworten:


10

Try (Dyalog) APL , 38 43 Bytes

Die letzte Eingabezeile muss mit einem Zeilenumbruch versehen sein.

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

Probieren Sie es online! Führen Sie in der Offline-Version von Dyalog APL ]boxing ON -style=minden gleichen Effekt aus.

Erläuterung

{... }eine anonyme Funktion, in der das Argument steht:

¯1 ⌽ ⍵ Drehen Sie den hinteren Zeilenvorschub nach vorne

(s ←... )definieren Sie die Funktion s wie folgt und wenden Sie sie an

  1 ↓¨ lassen Sie das erste Zeichen von jedem fallen

  ⊢ ⊂⍨ Linie, wo aufgeteilt

  ⊃ = ⊢ Das erste Zeichen entspricht den Zeichen in der Zeichenfolge

',' ,¨ Stellen Sie dann jeder Zeile ein Komma voran

Wenden Sie die Funktion s auf jede Zeile an

{... }wende nun die folgende anonyme Funktion an:

  1 ↓ ⍵ lösche das erste Element (die Zeilenüberschriften)

  ↓ ⍉ ↑ transponieren Sie die Liste der Zeilen in eine Liste der Spalten

  ↑¨ Machen Sie jedes Element (eine Liste von Einträgen) zu einer Matrix von aufgefüllten Einträgen

  ⍉ ⍪ In eine einspaltige Matrix umwandeln und dann in eine einzeilige Matrix umwandeln

  (⊃⍵) ⍪ setze das erste Element des Arguments (die Liste der Überschriften) oben drauf`

Hinweis: Während die Strichzeichnungszeichen in meiner Lösung nicht explizit verwendet werden, sind sie Teil des APL-Zeichensatzes und werden auch als einzelne Bytes gezählt.


Siehe Kommentare obenIs input using list or array of strings (and no newlines) valid? Nope.
edc65

@ edc65 Behoben. Vielen Dank.
Adám

Hah, dass Box - Display kommt sicherlich praktisch :)
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'┴')┘"

Ich habe das Gefühl, dass dies viel verbessert werden könnte, aber mir ging die Zeit davon. Alle Zeilenenden sind \nmit Nein \r, die Codierung ist UTF8 ohne Stückliste.


1

Schläger 578 Bytes

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

Ungolfed:

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

Testen:

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

Ausgabe:

┌──────┬───┬──────┐
│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('└┴┘'))

Verwendet padEnd, was FireFox-spezifisch ist.


1
Ist das nicht 288 Bytes?
Adám

1
@ Adám ... yes ... Fixed
Mwr247

Sie verwenden diese Menge, ist nicht g('└┴┘')gleichbedeutend mit g└┴┘(mit Backticks nach gund am Ende)?
NoOneIsHere

1
padEndist nicht standard. Sie sollten die erforderliche Ausführungsumgebung angeben.
Neil

1
Es gibt auch einige Stellen, an denen Sie schreiben `foo`+bar+`baz`- Sie können ein Byte mithilfe einer Vorlage speichern `foo${bar}baz`.
Neil

1

JavaScript (ES6), 281 Byte

Hinweis: Eingabe als einzelner String mit Zeilenumbrüchen - wie vom OP verlangt. Bei anderen Antworten wird eine Zeichenfolgenliste verwendet. Bei Verwendung eines Zeichenfolgenarrays in der Eingabe kann ich das erste Teilen und Ausschneiden von 9 Byte vermeiden.

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

Weniger golfen

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

Prüfung

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 Bytes

-3 Bytes für die %Formatierung und -1 für die Abkürzungstr.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)]))

Erfordert die Eingabe in Anführungszeichen.


1
Sieht aus wie 318 Bytes für mich.
Adám

1
@Adam Du hast recht, ich habe mir die Zeichen angesehen.
Karl Napf

Funktioniert nicht, da input()bei jedem Anruf nur eine Leitung belegt wird. Sie müssen anrufen, input()bis keine Leitungen mehr vorhanden sind, oder direkt von dort lesen stdin.
Movatica

Außerdem: 292 Bytes
movatica

0

696 Bytes

Golf gespielt:

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

Ungolfed (und schöner, weil das für niemanden von Nutzen ist):

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

Testen:

┌──────┬───┬──────┐         ┌──────────┬───────────────────────────┬─────┐
|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  |         └──────────┴───────────────────────────┴─────┘
└──────┴───┴──────┘

Irgendwie bekomme ich 697 Bytes, wenn ich das zähle.
Adám

@ Adám Gerade nochmal überprüft, ist die Golf-Zeichenfolge in Visual Studio 666 Spalten lang. Aber weder 666 noch 697 sind genau wettbewerbsfähige Ergebnisse :)
Pete Arden

Sie haben eine nachgestellte Newline, aber selbst wenn Sie diese entfernen, sind es immer noch 696 Bytes .
Adám

@ Adám Ah ... Ich habe auf eine Unstimmigkeit bei der Anzahl der Buchstaben / Bytes gewartet, um mich auszulösen. Sollte mit diesen lustigen Symbolen in diesem ("" ") gewusst haben. Aktualisiert, danke :)
Pete Arden

Siehe Kommentare obenIs input using list or array of strings (and no newlines) valid? Nope.
edc65

0

Perl, 273 + 9 ( -CS -nlaF,Flags) = 282 Bytes

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

Verwenden von:

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

Probieren Sie es auf Ideone .


0

PHP, 313 Bytes

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

Nervenzusammenbruch

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

Teste es bei ideone


0

APL (Dyalog Extended) , 36 25 Byte SBCS

Volles Programm. Nimmt das anABCDEFGHIJKLMNOPQRSTUVWXYZ ist die CSV-Datei. Druckt nach Standard.

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

Probieren Sie es online!

⎕A der Großbuchstabe A lphabet (kürzeste-zu-Referenz Einbau-String)
⎕CSV an Matrix , die Datei und Konvertieren von CSV lesen
m← Speichers als m(für m atrix)
1↓ der ersten Reihe fallen
 Transponierte
 aufgeteilt in Liste von Spalten
↑¨ jeder Liste von Zeichenketten in eine Matrix mischen
()⍪ Stapeln Sie darüber Folgendes:
1↑m Nehmen Sie die erste Zeile m
⌂disp , dfns.dispauf die angewendet werden soll (zeichnet Strichzeichnungszeichen).

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.