Xếp hàng CSV


12

Tổng quat:

Công việc của bạn là lấy đầu vào CSV theo key=valueđịnh dạng và sắp xếp nó theo cách có tổ chức hơn (xem bên dưới).

Đầu vào:

Luôn luôn thông qua stdin . Hồ sơ sẽ luôn ở dạng sau key=value:

foo=bar,baz=quux
abc=123,foo=fubar
baz=qwe,abc=rty,zxc=uiop,foo=asdf
  • Sẽ không có danh sách các khóa có thể trước, bạn phải tìm thấy chúng trong văn bản đầu vào.
  • Kết thúc đầu vào sẽ được báo hiệu bởi EOF, bất kỳ triển khai nào EOFphù hợp với HĐH của bạn.

Đầu ra:

Hàng đầu tiên của đầu ra của bạn sẽ là một danh sách tất cả các khóa, theo thứ tự bảng chữ cái (ngay cả khi các khóa là tất cả các số). Sau đó, in từng bản ghi ở cùng định dạng CSV tiêu đề số thích hợp, không có các phím được liệt kê. Vì vậy, với ví dụ trên, đầu ra chính xác sẽ là:

abc,baz,foo,zxc
,quux,bar,
123,,fubar,
rty,qwe,asdf,uiop

Câu hỏi thường gặp:

  • Tôi có phải lo lắng về đầu vào được định dạng không đúng?
    • Không. Chương trình của bạn có thể làm bất cứ điều gì nó muốn (ném ngoại lệ, bỏ qua, v.v.) nếu đầu vào không được định dạng chính xác, ví dụ: một dòng foo,bar,baz
  • Làm thế nào để tôi xử lý thoát khỏi các nhân vật đặc biệt?
    • Bạn có thể cho rằng sẽ không có thêm ,hoặc =trong dữ liệu không phải là một phần của key=valueđịnh dạng. "không có bất kỳ ý nghĩa đặc biệt nào trong cuộc thi này (mặc dù nó có trong CSV truyền thống). cũng không phải là đặc biệt trong bất kỳ cách nào.
    • Các dòng phải phù hợp với biểu thức chính sau: ^([^=,]+=[^=,]+)(,[^=,]+=[^=,]+)*$
      • Do đó, cả khóa và giá trị sẽ khớp [^=,]+
  • Thế còn CRLFso với LF?
    • Bạn có thể chọn bất kỳ dấu phân cách nào phù hợp với nền tảng của bạn. Hầu hết các ngôn ngữ xử lý điều này mà không có mã phân định đặc biệt.
  • Tôi có cần in dấu phẩy nếu vài cột cuối không tồn tại không?
    • Đúng. Xem ví dụ.
  • Các trình phân tích cú pháp CSV hoặc các công cụ bên ngoài tương tự khác có được phép không?
    • Không. Bạn phải tự phân tích dữ liệu.

15
FAQ khi chưa có ai đặt câu hỏi. :-)
Justin

5
@Quincunx Nếu tôi tự hỏi mình câu hỏi quan trọng;)
durron597

18
Tôi có cảm giác đó là cách tất cả các Câu hỏi thường gặp hoạt động.
Martin Ender

Tôi có thể có dấu phẩy trong danh sách các khóa và giá trị không? Nó sẽ làm cho mã của tôi ngắn hơn rất nhiều ...
PlasmaPower

@PlasmaPower Tôi không hiểu câu hỏi; tuy nhiên, chương trình của bạn phải khớp chính xác với đầu ra ví dụ cho đầu vào ví dụ đã cho
durron597

Câu trả lời:


3

GolfScript, 64 ký tự

n%{','/{'='/}%}%:I{{0=}/}%.&$:K','*n{`{{(2$=*}%''*\;}+K%','*n}I/

Mã này là một triển khai đơn giản trong GolfScript, bạn có thể kiểm tra ví dụ trực tuyến .

Mã chú thích:

# Split the input into lines, each line into tuples [key, value]
# and assign the result to variable I
n%{','/{'='/}%}%:I

# From each tuple take the 0'th element (i.e the key)
{{0=}/}%

# Take the unique items (.&), sort ($) and assign the result to variable K
.&$:K

# Output: join values with , and append a newline
','*n

# {...}I/: Loop over all lines of the input 
{

  # `{...}+K%: Loop over all keys and initially push the current 
  # line for each of the keys
  `{
    # stack here is [current key, current line]
    # {}%: map to all the items of the current line
    {
      # extract the key from the current item and compare
      (2$=
      # if equal keep [value], otherwise multiply with 0, i.e. discard
      *
    }%
    # join the results (may be one or zero) and drop the key
    ''*\; 
  }+K%
  # Output: join values of current line with , and append a newline
  ','*n
}I/

2

Perl 6: 119 ký tự, 120 byte

my@l=lines.map:{/[(\w+)\=(\w+)]+%\,/;push $!,~«@0;$%(@0 Z=>@1)}
say .join(",") for$!.=sort.=uniq,($(.{@$!}X//"") for@l)

Bỏ chơi gôn:

my@l=lines.map: {
    # Parse the key=value pairs,
    # put all the keys in $/[0] (or $0)
    # put all the values in $/[1] (or $1)
    / [ (\w+) \= (\w+) ]+ % \, /;

    # Push all the keys into $!
    # (@0 just means @$0 or $/[0].list)
    push $!, ~«@0;

    # Return a hash of keys zipped into pairs with the values
    $%( @0 Z=> @1 )
}

$!.=sort.=uniq;
# …i.e., $! = $!.sort.uniq;

# Print the CSV for the keys ($!),
# followed by the CSVs for the hashes we made for each line,
# as accessed by our sorted key list. (… .{@$!} …)
# If the value doesn't exist, just use "" instead. (… X// "" …)
say .join(",") for $!, ($( .{@$!} X// "" ) for @l)

2

perl, 129/121

129 byte, không có chuyển đổi dòng lệnh:

for(<>){push@x,{%g=map{split/=/}split/[,
]/};@h{keys%g}=()}@k=sort keys%h;$"=",";sub P{print"@_
"}P@k;for$x(@x){P map{$$x{$_}}@k}

Như @Dennis chỉ ra bên dưới, bạn có thể nhận được điều này tới 120 + 1 = 121 bằng cách sử dụng -n:

push@x,{%g=map{split/=/}split/[,
]/};@h{keys%g}=()}@k=sort keys%h;$"=",";sub P{print"@_
"}P@k;for$x(@x){P map{$$x{$_}}@k

Về cơ bản, đối với mỗi dòng, chúng tôi chia theo dấu phẩy để lấy danh sách các cặp. Đối với mỗi cặp, chúng tôi chia theo dấu bằng để lấy khóa và giá trị. Chúng tôi đặt cặp khóa / giá trị theo% h và hàm băm cục bộ. Các cựu được sử dụng để xác định danh sách các khóa. Cái sau được sử dụng để ghi nhớ các giá trị cho dòng này.


1
Bạn có thể lưu một vài ký tự bằng cách: 1. Sử dụng công -ntắc thay vì for(<>){...}. 2. Chia ra xung quanh [, ]thay vì sử dụng chomp. 3. Bỏ dấu chấm phẩy sau dấu ngoặc nhọn.
Dennis

Cảm ơn @Dennis. Tôi đã thực hiện 2 đề xuất sau của bạn. Tôi có thể chưa tham gia vào hỗn hợp nhưng tôi cảm thấy mình là một người thuần túy, quá lười để gõ vào điện thoại ATM của mình :-) Ngoài ra, điều đó sẽ yêu cầu khối END, nhưng tôi cho rằng đó vẫn là một chiến thắng ròng .
skibrianski

Vâng, thêm -n chỉ lưu 3 ký tự (hai điểm) với khối END. Tôi thích giải pháp "tinh khiết" hơn. Ít nhất cho đến khi một trong những câu trả lời khác đến gần hơn =)
skibrianski

Perl thực sự bao bọc while (<>) { ... }toàn bộ tập lệnh, do đó không cần khối END. Chỉ cần loại bỏ for(<>){ở đầu và }cuối tập lệnh.
Dennis

3
Tuy nhiên, nó sẽ hoạt động, miễn là bạn loại bỏ }phần cuối của tập lệnh chứ không phải phần tử tương ứng với forvòng lặp. Ngoài ra, bạn có thể lưu thêm một char bằng cách sử dụng một dòng mới thực tế thay vì \n.
Dennis

1

JavaScript ( ES5 ) 191 183 179 168 byte

Giả sử mã được chạy trong dòng lệnh spidermonkey:

for(b=[a={}];l=readline(i=0);b.push(c))for(c={},d=l.split(/,|=/);e=d[i++];)c[a[e]=e]=d[i++];for(;c=b[i++];)print(Object.keys(a).sort().map(function(x){return c[x]})+[])

Kết quả:

> js test.js < input.txt
abc,baz,foo,zxc
,quux,bar,
123,,fubar,
rty,qwe,asdf,uiop

Shim này có thể được sử dụng trong trình duyệt để mô phỏng spidermonkey readlineprint:

var I = 0, LINES = '\
foo=bar,baz=quux\n\
abc=123,foo=fubar\n\
baz=qwe,abc=rty,zxc=uiop,foo=asdf'.split('\n'),
readline = function(){
    return LINES[I++];
}, print = function(){
    return console.log.apply(console, arguments);
};

Ung dung:

a = {};                        // this object holds all keys found
b = [a];                       // array key:value pairs of each line, initialized with our key holder object in position 0
for(;l = readline();){         // store each line in l, loop until blank/undefined line
    c = {};                    // create a new object for this line's key:value pairs
    d = l.split(/,|=/);        // split line by commas and equals
    for(i = 0; e = d[i++];){   // loop through each key
        a[e] = e;              // set the key=key for key holder object
        c[e] = d[i++];         // set key=value for the line object
    }
    b.push(c);                 // push line object onto array
}
for(i = 0; c = b[i++];){       // loop through all line objects until undefined
    print(                     // print line
        Object.keys(a).sort(). // get sorted list of keys
        map(function(x){
            return c[x]        // map values from line object
        })
        + []                   // cast array to string
    );
}

Câu hỏi không nói rằng bạn phải sử dụng "thiết bị xuất chuẩn" - do đó bạn có thể sử dụng alertthay thế console.logvà lưu một số byte.
Gaurang Tandon

@GaurangTandon Sau đó, tôi phải nối tất cả các dòng phác thảo. Tôi có thể cập nhật câu trả lời của mình để sử dụng dòng lệnh spidermonkey và thay vào đó sử dụng readlineprintcho stdin / out thực tế
nderscore

1

Bash + coreutils, 188 138 byte

p=paste\ -sd,
f=`cat`
h=`tr , '\n'<<<$f|cut -d= -f1|sort -u`
$p<<<"$h"
for l in $f;{
join -o2.2 -a1 - <(tr =, ' \n'<<<$l|sort)<<<"$h"|$p
}

Đầu ra:

$ ./lineupcsv.sh < input.csv 
abc,baz,foo,zxc
,quux,bar,
123,,fubar,
rty,qwe,asdf,uiop
$ 

0

Haskell, 357 334

import Data.List
o=1<2
s u|u==""=""|o=tail u
t=takeWhile
d=dropWhile
c=(/=',')
e=(/='=')
p x|x/=""=Just((t e x,t c.s.d e$x),s.d c$x)|o=Nothing
g=m(unfoldr p).lines
k=nub.sort.(m fst=<<).g
[]#_=[]
(t@(x,u):z)#n@(a,b)|x==a=n:z|o=t:z#n
i=intercalate
main=interact$ \d->i"\n"$(i","$k d):m(i",".m snd.foldl(#)(m(flip(,)"").k$d))(g d)
m=map

gđang thực hiện phân tích cú pháp - nó phân tách đầu vào thành các dòng và ánh xạ mỗi dòng thành một danh sách các (key,value)cặp. k, bằng cách ghép tất cả các khóa vào một danh sách và loại bỏ trùng lặp, tạo một danh sách với tất cả các khóa duy nhất mà sau này tôi có thể sử dụng để sắp xếp. Tôi làm điều này bằng cách tạo một "Set" bên trong main( m(flip(,)"").k$d == [("abc",""),("baz",""),("foo",""),("zxc","")]) cho mỗi dòng, sau đó lấy từng (key,value)cặp từ một dòng và đặt nó ở vị trí của nó trong danh sách ( foldl). Dòng 1 từ sản lượng mẫu [("abc",""),("baz","quux"),("foo","bar"),("zxc","")], mà tôi ghép thành một Chuỗi ( ",quux,bar,"), nối với các dòng khác và in.

>>> csv.exe < input.txt
abc,baz,foo,zxc
,quux,bar,
123,,fubar,
rty,qwe,asdf,uiop

0

Python 2.7 - 242 byte

ôi

import os
c=[r.split(',')for r in os.read(0,99).split('\n')]
k=sorted(list(set(sum([[s.split('=')[0]for s in r]for r in c],[]))))
print','.join(k)
for l in c:
 t=[''for i in k]
 for s in l:
    o,v=s.split('=')
    t[k.index(o)]=v
 print','.join(t)

Lưu ý rằng lớp thụt thứ hai là một ký tự tab duy nhất, không phải bốn khoảng trắng như SE biểu hiện nó.

Ung dung:

#!/bin/python2

import os

# I do input as a list comprehension in the original but this is equivalent
c = []

# For each line in the input
for r in os.read(0,99).split('\n'):
    # Add a list of key=value pairs in that row to c
    c.append(r.split(','))

# Another thing done as a list comprehension, but I'll space it out
k = []

# For each list of key=value pair s in c
for r in c:
    # For each actual key=value pair in that list
    for s in r:
        # Get the key
        k.append(s.split('=')[0])

# Discard dupes by converting to set and back, then sort
k = sorted(list(set(k)))

# Seperate these keys by commas, then print
print ','.join(k)

# For each line in c
for l in c:
    # t has one empty string for each key in the input
    t = ['' for i in k]
    # For each key=value pair in the line
    for s in l:
        # o = key, v = value
        o, v = s.split('=')
        # Find the position that the key is in the list of keys, then put the
        # value in t at that position
        t[k.index(o)] = v

    # Now each value is in the right position and the keys with no values on this
    # line have an empty string. Join everything with commas and print
    print ','.join(t)

0

Con trăn 3: 200 195 192 189 187

import sys
r=[dict(p.split('=')for p in l[:-1].split(','))for l in sys.stdin]
x=set()
for d in r:x|=d.keys()
k=sorted(x)
for l in[k]+[[r.get(k,'')for k in k]for r in r]:print(*l,sep=',')

0

k4 (40? 51? 70? 46?)

biểu thức cơ bản là

","0:{(x@<x:?,/?!:'x)#/:x}(!).'"S=,"0:/:

cả hai đều chấp nhận và trả về một danh sách các chuỗi

để phù hợp với thông số kỹ thuật, chúng ta có thể tương tác làm

-1","0:{(x@<x:?,/?!:'x)#/:x}(!).'"S=,"0:/:."\\cat";

chấp nhận đầu vào từ stdin và in đầu ra ra thiết bị xuất chuẩn

đối với một ứng dụng độc lập chấp nhận đầu vào từ một đường ống, chúng ta có thể làm điều này:

$ cat i.k
.z.pi:{t,:`\:x}
.z.exit:{-1","0:{(x@<x:?,/?!:'x)#/:x}(!).'"S=,"0:/:t}
$ cat i.txt|q i.k
abc,baz,foo,zxc
,quux,bar,
123,,fubar,
rty,qwe,asdf,uiop
$ 

altho nếu bạn sẵn sàng xem xét trình bao bọc k-as-filter trước đó của tôi, awq.k, như một công cụ chấp nhận được cho loại câu đố này, thì chúng ta có thể làm điều này:

$ cat i.txt|awq.k '","0:{(x@<x:?,/?!:'\''x)#/:x}(!).'\''"S=,"0:/:'

đó là 46 ký tự hoặc 40 ký tự, tùy thuộc vào cách bạn đếm trích dẫn shell


Những loại môi trường là cần thiết để chạy này? qchỉ huy? Được awq.kxuất bản ở đâu đó?
Chấn thương kỹ thuật số

Q 32 bit hiện có sẵn dưới dạng phần mềm miễn phí từ kx.com/software-doad.php . (trước đây họ chỉ có phiên bản dùng thử giới hạn thời gian miễn phí.) hmm, có vẻ như awq không thực sự được xuất bản ở bất cứ đâu; tôi nên làm gì đó về điều đó
Aaron Davies

0

C # - 369

(trong LINQPAD)

void C(string a){var k=a.Split(new[]{',','\n'}).Select(s=>s.Split('=')[0]).OrderBy(o=>o).Distinct();var t=string.Join(",", k)+"\n";foreach(var x in a.Split('\n')){for(int i=0;i<k.Count();i++){foreach(var y in x.Split(',').OrderBy(o=>o.Split('=')[0]))if(k.ElementAt(i)==y.Split('=')[0])t+=y.Split('=')[1];t+=",";}t=t.Remove(t.LastIndexOf(','),1)+"\n";}Console.Write(t);}

Ung dung

void C(string a)
{
    var k=a.Split(new[]{',','\n'}).Select(s=>s.Split('=')[0]).OrderBy(o=>o).Distinct();
    var t=string.Join(",", k)+"\n";
    foreach(var x in a.Split('\n'))
    {
        for(int i=0;i<k.Count();i++)
        {
            foreach(var y in x.Split(',').OrderBy(o=>o.Split('=')[0]))
                if(k.ElementAt(i)==y.Split('=')[0])
                    t+=y.Split('=')[1];
            t+=",";
        }
        t=t.Remove(t.LastIndexOf(','),1)+"\n";
    }
    Console.Write(t);
}

Kiểm tra đầu vào chuỗi

C("foo=bar,baz=quux\nabc=123,foo=fubar\nbaz=qwe,abc=rty,zxc=uiop,foo=asdf");

Đầu ra

abc,baz,foo,zxc
,quux,bar,
123,,fubar,
rty,qwe,asdf,uiop

Chỉ tò mò, đây là C # vì vậy nó nên hoạt động trong windows, nhưng phải không? (Xem câu hỏi CRLFso với LFCâu hỏi thường gặp của tôi ) Thật không may, tôi không có bản sao Visual Studio để kiểm tra.
durron597

Tôi ban đầu nên đã thêm ghi chú, nhưng tôi có bây giờ. Có nó hoạt động. Tôi đã tạo và thử nghiệm nó trong linqpad. Tôi chưa thử nghiệm nó trong ứng dụng console, nhưng không có lý do nào khiến nó không hoạt động. Nhưng một ứng dụng giao diện điều khiển rõ ràng sẽ thêm nhiều byte vào mã.
jzm
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.