Zählen Sie die Anzahl der Felder in jedem CSV-Datensatz

12

Stellen Sie sich eine Textdatei vor, in der jeder CSV-Datensatz möglicherweise eine andere Anzahl von Feldern enthält. Die Aufgabe besteht darin, Code zu schreiben, um auszugeben, wie viele Felder sich in jedem Datensatz der Datei befinden. Sie können davon ausgehen, dass die Datei keine Kopfzeile enthält, und Sie können nach Belieben aus einer Datei oder einer Standardeingabe einlesen.

Sie können eine Version von rfc4180 für die CSV-Regeln annehmen, die ich unten für die Definition jeder Zeile der Datei erläutere. Hier ist eine leicht bearbeitete Version des relevanten Teils der Spezifikation:

Definition des CSV-Formats

  1. Jeder Datensatz befindet sich in einer separaten Zeile, die durch einen Zeilenumbruch (CRLF) begrenzt ist. Beispielsweise:

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

  2. Der letzte Datensatz in der Datei enthält möglicherweise einen Zeilenumbruch am Ende oder nicht. Beispielsweise:

    aaa,bbb,ccc CRLF
    zzz,yyy,xxx

(Regel 3. gilt nicht für diese Herausforderung)

  1. In jedem Datensatz können sich ein oder mehrere Felder befinden, die durch Kommas getrennt sind. Leerzeichen werden als Teil eines Feldes betrachtet und sollten nicht ignoriert werden.

  2. Jedes Feld kann in doppelte Anführungszeichen eingeschlossen sein oder nicht. Wenn Felder nicht in doppelte Anführungszeichen eingeschlossen sind, werden in den Feldern möglicherweise keine doppelten Anführungszeichen angezeigt. Beispielsweise:

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

  3. Felder, die Zeilenumbrüche (CRLF), doppelte Anführungszeichen und Kommas enthalten, sollten in doppelte Anführungszeichen eingeschlossen werden. Beispielsweise:

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

  4. Wenn Felder in Anführungszeichen gesetzt werden, muss ein Anführungszeichen, das in einem Feld steht, durch ein weiteres Anführungszeichen maskiert werden. Beispielsweise:

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

Beispiel

Eingang:

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

Sollte die Ausgabe geben:

2, 3, 3, 5

Sie können die Ausgabewerte so angeben, wie Sie es am bequemsten finden.

Bibliotheken

Sie können jede beliebige Bibliothek verwenden.


Bisher fantastische Antworten, aber wir vermissen eine Kommandozeilen- / Bash-Antwort, die besonders cool wäre.

Anush
quelle

Antworten:

5

Stax , 19 12 Bytes

èJ§3‼}vAà○L>

Führen Sie es aus, und debuggen Sie es

Ausgepackt, ungolfed und kommentiert sieht es so aus.

_'"/    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

Führen Sie dieses aus

rekursiv
quelle
1
Wie funktioniert es?
Anush
1
@ Anush: Ich habe einige weitere Informationen hinzugefügt.
rekursiver
4

R , 40 Bytes

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

Probieren Sie es online!

Gemäß der Dokumentation von erhalten count.fieldsFelder mit Zeilenumbrüchen eine Feldanzahl von NA für die Anfangszeile, sodass wir sie herausfiltern.

Giuseppe
quelle
3

JavaScript (ES2018), 42 bis 59 Byte

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

Rick Hitchcock
quelle
Technisch ist dies ES2018 aufgrund der sFlagge auf der Regex. Nicht, dass es so wichtig wäre ;-) Und netter Gebrauch davon, übrigens!
ETHproductions
2
Diese Funktion scheint immer nur für einen Datensatz zu funktionieren. Ich denke, die Problembeschreibung erfordert die Behandlung einer gesamten Datei mit mehreren Datensätzen.
rekursive
@ETHproductions, guter Punkt, wird aktualisiert.
Rick Hitchcock
@recursive, du hast recht, ich habe die Eingaben falsch verstanden. Jetzt aktualisiert, beim Verlust von vielen, vielen Bytes.
Rick Hitchcock
3

Gelee , 12 Bytes

ṣ”"m2FỴ=”,§‘

Eine Portierung der rekursiven Stax-Antwort - geben Sie Kredit!

Probieren Sie es online!

Wie?

ṣ”"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)

Vielleicht bevorzugen Sie ṣ”"m2ẎỴċ€”,‘- ist fest und ċ€zählt die Kommas in jedem.

Jonathan Allan
quelle
2

Python, 63 Bytes

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

Gibt die Ausgabe in einem iterierbaren mapObjekt zurück.

SlayerGames44
quelle
2
Unter Verwendung einer lambdaFunktion können Sie diese nach unten bekommen 54 Bytes
ovs
@ovs Ich verstehe die Regeln möglicherweise nicht, aber Ihr TIO scheint die Eingabe vorbereitet zu haben. Ist das wirklich gültig?
Anush
Ich verstehe, warum es jetzt funktioniert (dank nur @ ASCII).
Anush
2

Perl 5 .10.0, 55 53 Bytes

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

Probieren Sie es online!

Erläuterung:

$_=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
wastl
quelle
2

Java 10, 101 Bytes

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

Probieren Sie es online aus.

Erläuterung:

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
quelle