Convertir CSV en table


15

Le défi

Étant donné une entrée CSV, sortez une table Unicode appropriée en utilisant des caractères de boîte.

Mise en page

Le tableau sera formaté selon les règles suivantes:

  • La largeur de colonne sera égale à la valeur la plus longue de cette colonne
  • Toutes les données du tableau seront justifiées à gauche
  • Chaque table suppose que la première ligne csv est l'en-tête
  • Le tableau utilisera les caractères suivants pour ses bordures:

┌ ┬ ┐ ├ ┼ ┤ └ ┴ ┘ ─ │

Exemple

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

Règles

  • Des échappatoires standard s'appliquent
  • Vous pouvez soumettre un programme complet, une fonction ou un lambda
  • L'entrée peut provenir d'un fichier, d'un argument de programme ou de toute alternative acceptable
  • La sortie peut être vers un fichier, retournée ou toute autre alternative acceptable
  • L'entrée CSV doit prendre le même format que celui utilisé dans mon exemple.
  • La réponse la plus courte en octets l'emporte.

L'entrée CSV doit prendre la forme suivante:

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

2
Je pense qu'il y a essentiellement deux façons de procéder avec la définition CSV. Si la partie intéressante du problème est la sortie, vous pouvez la rendre aussi simple que "fractionner sur des virgules" et ne pas avoir à vous soucier de la façon de citer les virgules et de citer le caractère de citation. Sinon, vous pouvez indiquer une méthode spécifique d'analyse syntaxique du CSV ("les guillemets doubles activent un mode dans lequel les virgules sont ignorées, deux guillemets consécutifs produisent une guillemet double littérale" est assez courante, mais en aucun cas la seule existant).

4
Euh, grave problème: vous n'avez pas spécifié de condition de victoire. À quoi servent les programmes à optimiser? Longueur ( code-golf )?

1
Au moins les trois premiers liens définissent tous CSV différemment (et au moins deux disent qu'il existe de nombreuses façons de le faire). Je suppose donc que "CSV" doit être défini plus complètement pour être utilisé dans une question (et que les solutions essaieront de se séparer des virgules et de ne pas gérer les échappements car cela leur permet d'être plus courts).

2
D'accord, j'ai modifié la question pour inclure des détails sur le format CSV que j'aimerais que tout le monde utilise.
Shaun Wild

1
CRLF? Sérieusement? Cela va donner une pénalité assez importante sur Unix, où CR signifie autre chose dans les fichiers texte. Vous voudrez probablement simplement remplacer cela par "newline", permettant d'utiliser la nouvelle ligne spécifique au système d'exploitation.

Réponses:


10

Essayez (Dyalog) APL , 38 43 octets

La dernière ligne d'entrée doit avoir une nouvelle ligne de fin.

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

Essayez-le en ligne! Dans la version hors ligne de Dyalog APL, exécutez ]boxing ON -style=minpour le même effet.

Explication

{... }une fonction anonyme où représente l'argument:

¯1 ⌽ ⍵ faire pivoter la nouvelle ligne de fin vers l'avant

(s ←... )définissez la fonction s comme suit et appliquez-la

  1 ↓¨ déposez le premier caractère de chaque

  ⊢ ⊂⍨ ligne, divisée où

  ⊃ = ⊢ le premier caractère est égal aux caractères de la chaîne

',' ,¨ puis ajoutez une virgule à chaque ligne

appliquer la fonction s à chaque ligne

{... }appliquez maintenant la fonction anonyme suivante:

  1 ↓ ⍵ déposez le premier élément (les en-têtes de ligne)

  ↓ ⍉ ↑ transposer la liste des lignes en liste des colonnes

  ↑¨ faire de chaque élément (une liste d'entrées) une matrice d'entrées rembourrées

  ⍉ ⍪ transformer en matrice à une colonne, puis transposer en matrice à une rangée

  (⊃⍵) ⍪ mettre le premier élément de l'argument (la liste des en-têtes) en haut`

Remarque: Bien que les caractères de dessin au trait ne soient pas explicitement utilisés dans ma solution, ils font partie du jeu de caractères APL et seraient également comptés comme des octets uniques.


Voir les commentaires ciIs input using list or array of strings (and no newlines) valid? Nope.
edc65

@ edc65 Fixé. Merci.
Adám

Hah, cet affichage en boîte est certainement utile :)
Ven

2

PowerShell 3+, 365 octets

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

J'ai l'impression que cela pourrait être beaucoup amélioré, mais j'ai manqué de temps. Toutes les fins de ligne sont \nsans \r, le codage est UTF8 sans BOM.


1

Raquette 578 octets

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

Non golfé:

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

Essai:

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

Production:

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

1

JavaScript (ES6 | FireFox), 286 octets

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

Utilise padEnd, qui est spécifique à FireFox.


1
N'est-ce pas 288 octets?
Adám

1
@ Adám ... oui ... Corrigé
Mwr247

Vous l'utilisez beaucoup, n'est-ce pas g('└┴┘')équivalent à g└┴┘(avec des crochets après get à la fin)?
NoOneIsHere

1
padEndn'est pas standard. Vous devez spécifier l'environnement d'exécution nécessaire.
Neil

1
En outre, il y a quelques endroits où vous écrivez `foo`+bar+`baz`- vous pouvez enregistrer un octet en utilisant un modèle `foo${bar}baz`.
Neil

1

JavaScript (ES6), 281 octets

Remarque: entrée sous forme de chaîne unique avec des retours à la ligne - comme demandé par OP. D'autres réponses utilisent une liste de chaînes - en utilisant un tableau de chaînes en entrée, je peux éviter le premier fractionnement et couper 9 octets.

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

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

Tester

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 octets

-3 octets pour utiliser la %mise en forme et -1 pour abrégerstr.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)]))

Nécessite une entrée entre guillemets.


1
On dirait 318 octets pour moi.
Adám

1
@ Adám Tu as raison, j'ai regardé les caractères.
Karl Napf

Ne fonctionne pas, car input()ne prend qu'une seule ligne à chaque appel. Vous devrez appeler input()jusqu'à ce qu'il n'y ait plus de lignes ou lire directement depuis stdin.
movatica

En plus de cela: 292 octets
movatica

0

C #, 696 octets

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

Non golfé (et plus agréable, car ^ cela ne sert à personne):

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

Essai:

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

D'une manière ou d'une autre, je continue à obtenir 697 octets lors du comptage.
Adám

@ Adám Juste vérifié à nouveau, la chaîne Golfed est longue de 666 colonnes dans Visual Studio. Mais ni 666 ni 697 ne sont exactement des scores compétitifs de toute façon :)
Pete Arden

Vous avez une nouvelle ligne de fin, mais même lors de sa suppression, elle est toujours de 696 octets .
Adám

@ Adám Ah ... J'attendais une différence de nombre de lettres / nombre d'octets pour me trébucher. Aurait dû savoir avec ces symboles drôles dans celui-ci ("┼"). Mis à jour, merci :)
Pete Arden

Voir les commentaires ciIs input using list or array of strings (and no newlines) valid? Nope.
edc65

0

Perl, 273 + 9 ( -CS -nlaF,drapeaux) = 282 octets

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

En utilisant:

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

Essayez-le sur Ideone .


0

PHP, 313 octets

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

panne

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

Testez-le chez ideone


0

APL (Dyalog Extended) , 36 25 octets SBCS

Programme complet. Suppose queABCDEFGHIJKLMNOPQRSTUVWXYZ c'est le fichier CSV. Imprime à stdout.

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

Essayez-le en ligne!

⎕A les majuscules A lphabet (la plus courte à la référence chaîne incorporé) la
⎕CSV lecture du document et converti à partir de CSV à matrice
m← magasin que m(pour m atrice)
1↓ déposer la première rangée
 transposer
 divisée en liste des colonnes
↑¨ mélanger chaque liste de chaînes de caractères dans une matrice
(... )⍪ empilez ce qui suit en plus de cela:
1↑m prenez la première ligne de m
⌂disp appliquer dfns.dispà cela (dessine des caractères de dessin au trait)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.