แปลง CSV เป็น Table


15

ความท้าทาย

เมื่อได้รับอินพุต CSV ให้ส่งออกตาราง Unicode ที่เหมาะสมโดยใช้อักขระแบบกล่อง

การจัดรูปแบบ

ตารางจะถูกจัดรูปแบบโดยใช้กฎต่อไปนี้:

  • ความกว้างของคอลัมน์จะเท่ากับค่าที่ยาวที่สุดของคอลัมน์นั้น
  • ข้อมูลในตารางทั้งหมดจะถูกปรับให้เป็นธรรม
  • แต่ละตารางจะถือว่าแถว csv แรกเป็นส่วนหัว
  • ตารางจะใช้อักขระต่อไปนี้สำหรับเส้นขอบ:

┌ ┬ ┐ ├ ┼ ┤ └ ┴ ┘ ─ │

ตัวอย่าง

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

กฎระเบียบ

  • ช่องโหว่มาตรฐานใช้
  • คุณสามารถส่งโปรแกรมแบบเต็มฟังก์ชั่นหรือแลมบ์ดา
  • อินพุตอาจมาจากไฟล์อาร์กิวเมนต์ของโปรแกรมหรือตัวเลือกอื่นที่ยอมรับได้
  • เอาต์พุตสามารถเป็นไฟล์ส่งคืนหรือเป็นทางเลือกที่ยอมรับได้
  • อินพุต CSV ควรใช้รูปแบบเดียวกับที่ใช้ในตัวอย่างของฉัน
  • คำตอบที่สั้นที่สุดในการชนะไบต์

อินพุต CSV ควรใช้แบบฟอร์มต่อไปนี้:

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

2
ฉันคิดว่ามีสองวิธีที่คุณสามารถไปกับคำจำกัดความของ CSV ได้ หากส่วนที่น่าสนใจของปัญหาคือผลลัพธ์คุณสามารถทำให้มันง่ายเหมือน "split on จุลภาค" และไม่ต้องกังวลเกี่ยวกับวิธีการพูดเครื่องหมายจุลภาคและวิธีการพูดอักขระเครื่องหมายคำพูด มิฉะนั้นคุณสามารถระบุวิธีการเฉพาะในการแยกวิเคราะห์ CSV ("เครื่องหมายคำพูดคู่สลับโหมดที่เครื่องหมายจุลภาคจะถูกละเว้นเครื่องหมายคำพูดคู่สองตัวในแถวสร้างเครื่องหมายคำพูดคู่ที่แท้จริง" เป็นวิธีทั่วไป แต่ไม่มีวิธีเดียวเท่านั้น ในการดำรงอยู่)

4
เอ่อปัญหาร้ายแรง: คุณไม่ได้ระบุเงื่อนไขแห่งชัยชนะ โปรแกรมใดที่ควรได้รับการปรับให้เหมาะสม ความยาว ( รหัส - กอล์ฟ )?

1
อย่างน้อยสามลิงค์แรกนั้นมีการกำหนด CSV ต่างกัน (และอย่างน้อยสองคนบอกว่ามีวิธีที่แตกต่างมากมายในการทำ) ดังนั้นฉันจึงสันนิษฐานว่า "CSV" จะต้องมีการกำหนดไว้อย่างสมบูรณ์มากขึ้นสำหรับการใช้งานในคำถาม (และโซลูชันจะพยายามแยกออกด้วยเครื่องหมายจุลภาคและไม่ต้องจัดการกับการหลบหนีเพราะจะทำให้สั้นลง)

2
โอเคฉันได้แก้ไขคำถามเพื่อรวมเฉพาะเกี่ยวกับรูปแบบ CSV ที่ฉันต้องการให้ทุกคนใช้
Shaun Wild

1
CRLF? อย่างจริงจัง? นั่นจะเป็นการลงโทษที่ค่อนข้างใหญ่สำหรับ Unix โดยที่ CR หมายถึงอย่างอื่นในไฟล์ข้อความ คุณอาจต้องการแทนที่ด้วย "newline" ซึ่งอนุญาตให้ใช้ newline เฉพาะระบบปฏิบัติการ

คำตอบ:


10

ลอง (Dyalog) APL , 38 43 ไบต์

บรรทัดอินพุตสุดท้ายต้องมีบรรทัดใหม่ต่อท้าย

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

ลองออนไลน์! ใน Dyalog APL เวอร์ชั่นออฟไลน์ให้เรียกใช้]boxing ON -style=minงานเอฟเฟกต์เดียวกัน

คำอธิบาย

{... }ฟังก์ชั่นที่ไม่ระบุชื่อซึ่งแสดงถึงการโต้แย้ง:

¯1 ⌽ ⍵ หมุนขึ้นบรรทัดใหม่ไปที่ด้านหน้า

(s ←... )กำหนดฟังก์ชั่นsดังต่อไปนี้และนำไปใช้

  1 ↓¨ วางอักขระตัวแรกของแต่ละตัว

  ⊢ ⊂⍨ เส้นแยกที่

  ⊃ = ⊢ อักขระตัวแรกเท่ากับอักขระในสตริง

',' ,¨ จากนั้นเติมเครื่องหมายจุลภาคต่อแต่ละบรรทัด

ใช้ฟังก์ชันsกับแต่ละบรรทัด

{... }ตอนนี้ใช้ฟังก์ชันที่ไม่ระบุชื่อต่อไปนี้:

  1 ↓ ⍵ ปล่อยองค์ประกอบแรก (ส่วนหัวของแถว)

  ↓ ⍉ ↑ ย้ายรายการแถวลงในรายการคอลัมน์

  ↑¨ ทำให้แต่ละองค์ประกอบ (รายการของรายการ) เป็นเมทริกซ์ของรายการเบาะ

  ⍉ ⍪ ทำเป็นเมทริกซ์แบบคอลัมน์เดียวจากนั้นแปลงเป็นเมทริกซ์แบบแถวเดียว

  (⊃⍵) ⍪ ใส่องค์ประกอบแรกของการโต้แย้ง (รายการส่วนหัว) ที่ด้านบน `

หมายเหตุ:แม้ว่าอักขระการวาดเส้นจะไม่ได้ใช้อย่างชัดเจนในโซลูชันของฉัน แต่ก็เป็นส่วนหนึ่งของชุดอักขระ APL และจะนับเป็นไบต์เดียวด้วย


ดูความคิดเห็นด้านบนIs input using list or array of strings (and no newlines) valid? Nope.
edc65

@ edc65 แก้ไข ขอบคุณ
Adám

ฮะว่าการแสดงผลชนิดบรรจุกล่องก็มาในที่มีประโยชน์ :)
Ven

2

PowerShell 3+, 365 ไบต์

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

ฉันรู้สึกว่าสิ่งนี้สามารถปรับปรุงได้มากมาย แต่ฉันก็ไม่มีเวลา การสิ้นสุดบรรทัดทั้งหมด\nไม่มีการ\rเข้ารหัสคือ UTF8 ที่ไม่มี BOM


1

แร็กเก็ต 578 ไบต์

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

การทดสอบ:

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

เอาท์พุท:

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

1

JavaScript (ES6 | FireFox), 286 ไบต์

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

ใช้padEndซึ่งเป็น FireFox เฉพาะ


1
ไม่ใช่ 288 ไบต์ใช่ไหม
Adám

1
@ Adám ... ใช่ ... แก้ไขแล้ว
Mwr247

คุณใช้มากนี้ไม่g('└┴┘')เทียบเท่ากับg└┴┘(กับ backticks หลังgและสิ้นสุด)?
NoOneIsHere

1
padEndไม่ได้มาตรฐาน คุณควรระบุสภาพแวดล้อมการดำเนินการที่จำเป็น
Neil

1
นอกจากนี้ยังมีคู่ของสถานที่ที่คุณเขียน`foo`+bar+`baz`- `foo${bar}baz`คุณสามารถประหยัดไบต์โดยใช้แม่แบบ
Neil

1

JavaScript (ES6), 281 ไบต์

หมายเหตุ: อินพุตเป็นสตริงเดี่ยวที่มีบรรทัดใหม่ - ตามที่ร้องขอโดย OP คำตอบอื่น ๆ ใช้รายการสตริง - การใช้อาร์เรย์สตริงในอินพุตฉันสามารถหลีกเลี่ยงการแยกและตัด 9 ไบต์แรก

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

น้อย golfed

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

ทดสอบ

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 ไบต์

-3 ไบต์สำหรับการใช้การ%จัดรูปแบบและ -1 สำหรับตัวย่อstr.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)]))

ต้องการอินพุตที่อยู่ในเครื่องหมายคำพูด


1
ดูเหมือนว่า 318 ไบต์กับฉัน
59

1
@ Adámคุณพูดถูกฉันดูที่ตัวอักษร
Karl Napf

ไม่ทำงานเนื่องจากinput()ใช้เพียงหนึ่งบรรทัดในแต่ละการโทร คุณจะต้องเรียกจนกว่าจะไม่มีเส้นเพิ่มเติมหรืออ่านได้โดยตรงจากinput() stdin
movatica

นอกจากนั้น: 292 ไบต์
movatica

0

C #, 696 ไบต์

แข็งแรงเล่นกอล์ฟ:

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 (และดีกว่าเพราะ ^ นั่นไม่มีประโยชน์กับใคร):

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

การทดสอบ:

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

อย่างไรก็ตามฉันได้รับ 697 ไบต์เมื่อนับจำนวนนี้
Adám

@ Adámตรวจสอบอีกครั้งสตริง Golfed มีความยาว 666 คอลัมน์ใน Visual Studio แต่ไม่ 666 หรือ 697 มีคะแนนในการแข่งขันว่าล่ะค่ะ :)
พีอาร์เดน

คุณมีการขึ้นบรรทัดใหม่ต่อท้าย แต่แม้เมื่อถอดมันก็ยังคงเป็น 696 ไบต์
Adám

@ Adámอ่า ... ฉันรอดูความแตกต่างของตัวอักษร / จำนวนไบต์เพื่อรอฉัน ควรรู้จักสัญลักษณ์ตลกเหล่านี้ในอันนี้ ("┼") อัปเดต, ขอบคุณ :)
Pete Arden

ดูความคิดเห็นด้านบนIs input using list or array of strings (and no newlines) valid? Nope.
edc65

0

Perl, 273 + 9 ( -CS -nlaF,ธง) = 282 ไบต์

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

โดยใช้:

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

ลองบนIdeone


0

PHP, 313 ไบต์

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

ชำรุด

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

ทดสอบที่ ideone


0

APL (Dyalog Extended) , 36 25 ไบต์ SBCS

โปรแกรมเต็มรูปแบบ ถือว่าABCDEFGHIJKLMNOPQRSTUVWXYZเป็นไฟล์ CSV พิมพ์ไปยัง stdout

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

ลองออนไลน์!

⎕A ตัวพิมพ์ใหญ่A lphabet (สตริงในตัวที่สั้นที่สุดเพื่ออ้างอิง)
⎕CSV  อ่านว่าไฟล์และแปลงจาก CSV เพื่อเมทริกซ์
m← เก็บไว้เป็นm(สำหรับม. Atrix)
1↓ วางแถวแรก
 transpose
 แยกออกเป็นรายการของคอลัมน์
↑¨  ผสมรายการของสตริงในแต่ละเมทริกซ์
(…จัด)⍪ วางสิ่งต่อไปนี้ไว้ด้านบน:
1↑m นำแถวแรกm
⌂disp ไปใช้dfns.dispกับที่นั้น (ดึงอักขระการวาดเส้น)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.