Policz liczbę pól w każdym rekordzie csv

12

Wyobraź sobie plik tekstowy, w którym każdy rekord csv może mieć inną liczbę pól. Zadanie polega na napisaniu kodu, który wyświetli liczbę pól w każdym rekordzie pliku. Możesz założyć, że w pliku nie ma linii nagłówka i możesz czytać z pliku lub ze standardowego wejścia, zgodnie z wyborem.

Możesz założyć wersję rfc4180 dla reguł csv, które wyjaśnię poniżej dla definicji każdej linii pliku. Oto lekko edytowana wersja odpowiedniej części specyfikacji:

Definicja formatu CSV

  1. Każdy rekord znajduje się w osobnej linii, oddzielonej linią podziału (CRLF). Na przykład:

    aaa,bbb,ccc CRLF
    zzz,yyy,xxx CRLF

  2. Ostatni rekord w pliku może, ale nie musi, mieć kres końca linii. Na przykład:

    aaa,bbb,ccc CRLF
    zzz,yyy,xxx

(Zasada 3. nie dotyczy tego wyzwania)

  1. W każdym rekordzie może znajdować się jedno lub więcej pól oddzielonych przecinkami. Spacje są uważane za część pola i nie należy ich ignorować.

  2. Każde pole może, ale nie musi, być ujęte w podwójne cudzysłowy. Jeśli pola nie są ujęte w podwójne cudzysłowy, wówczas podwójne pola mogą nie pojawiać się w polach. Na przykład:

    "aaa","bbb","ccc" CRLF
    zzz,yyy,xxx

  3. Pola zawierające podział wiersza (CRLF), podwójne cudzysłowy i przecinki powinny być ujęte w cudzysłowy. Na przykład:

    "aaa","b CRLF
    bb","ccc" CRLF
    zzz,yyy,xxx

  4. Jeśli do zamykania pól stosowane są cudzysłowy, wówczas cytat pojawiający się w polu musi być poprzedzony innym podwójnym cudzysłowem. Na przykład:

    "aaa","b""bb","ccc"

Przykład

Wejście:

,"Hello, World!"
"aaa","b""bb","ccc"
zzz,yyy,
"aaa","b 
bb","ccc","fish",""

Powinien dać wynik:

2, 3, 3, 5

Możesz podać wartości wyjściowe w dowolny dogodny dla siebie sposób.

Biblioteki

Możesz użyć dowolnej biblioteki, którą lubisz.


Do tej pory niesamowite odpowiedzi, ale brakuje nam linii poleceń / odpowiedzi bash, co byłoby szczególnie fajne.

Anush
źródło

Odpowiedzi:

5

Stax , 19 12 bajtów

èJ§3‼}vAà○L>

Uruchom i debuguj

Rozpakowane, niepolowane i skomentowane, wygląda to tak.

_'"/    split *all* of standard input by double quote characters
2::     keep only the even numbered elements
|j      split on newlines (implicitly concatenates array of "strings")
m       for each line, execute the rest of the program and output
  ',#^  count the number of commas occurring as substrings, and increment

Uruchom ten

rekurencyjny
źródło
1
Jak to działa?
Anush
1
@Anush: Dodałem trochę więcej informacji.
rekurencyjny
4

R , 40 bajtów

(x=count.fields(stdin(),","))[!is.na(x)]

Wypróbuj online!

Na tej dokumentacji z count.fieldspola z przerwami liniowych uzyskać liczbę pól z NA na początkowym linii, więc je odfiltrować.

Giuseppe
źródło
3

JavaScript (ES2018), 42 59 bajtów

s=>s.replace(/".+?"/sg).split`\n`.map(c=>c.split`,`.length)

Rick Hitchcock
źródło
Technicznie jest to ES2018 ze względu na sflagę wyrażenia regularnego. Nie żeby to miało tak duże znaczenie ;-) I miłe z tego, przy okazji!
ETHproductions
2
Ta funkcja działa tylko na jeden rekord na raz. Myślę, że opis problemu wymaga obsługi całego pliku zawierającego wiele rekordów.
rekursywny
@ETHproductions, dobra uwaga, zostanie zaktualizowany.
Rick Hitchcock,
@recursive, masz rację, źle zrozumiałem dane wejściowe. Teraz zaktualizowane, z utratą wielu wielu bajtów.
Rick Hitchcock,
3

Galaretka , 12 bajtów

ṣ”"m2FỴ=”,§‘

Port odpowiedzi rekurencyjnej Staxa - idź, daj kredyt!

Wypróbuj online!

W jaki sposób?

ṣ”"m2FỴ=”,§‘ - Link: list of characters, V
 ”"          - a double quote character = '"'
ṣ            - split (V) at ('"')
   m2        - modulo slice with two (1st, 3rd, 5th, ... elements of that)
     F       - flatten list of lists to a list
      Ỵ      - split at newlines
        ”,   - comma character = ','
       =     - equal? (vectorises)
          §  - sum each
           ‘ - increment (vectorises)
             - (as a full program implicit print)

Może wolisz ṣ”"m2ẎỴċ€”,‘- jest zaostrzony i ċ€liczy przecinki w każdym.

Jonathan Allan
źródło
2

Python, 63 bajty

import csv
def f(s):return map(len,csv.reader(s.split("\n"))

Zwraca wynik w mapobiekcie iterowalnym .

SlayerGames44
źródło
2
Za pomocą lambdafunkcji możesz sprowadzić to do 54 bajtów
dniu
@ovs Może nie rozumiem zasad, ale wydaje się, że twoje TIO przygotowało dane wejściowe. Czy to naprawdę ważne?
Anush,
Rozumiem, dlaczego teraz działa (tylko dzięki @ ASCII).
Anush,
2

Perl 5 .10,0, 55 53 bajtów

$_=shift;s/"(""|[^"])*"//g;s/^.*$/1+$&=~y:,::/gem;say

Wypróbuj online!

Wyjaśnienie:

$_=shift;          # first command-line arg
s/"(""|[^"])*"//g; # remove quoted fields
s/^.*$/            # replace each line       
  1+$&=~y:,::      # by the number of commas plus 1
/gem;
say                # print
pustkowie
źródło
2

Java 10, 101 bajtów

s->{for(var p:s.replaceAll("\"[^\"]*\"","x").split("\n"))System.out.println(p.split(",",-1).length);}

Wypróbuj online.

Wyjaśnienie:

s->{                                    // Method with String parameter and no return-type
  for(var p:s.replaceAll("\"[^\"]*\"","x") 
                                        //  Replace all words within quotes with an "x"
             .split("\n"))              //  Then split by new-line and loop over them:
    System.out.println(p.split(",",-1)  //   Split the item by comma's
                        .length);}      //   And print the length of this array
Kevin Cruijssen
źródło