Contare il numero di campi in ciascun record CSV


12

Immagina un file di testo in cui ogni record CSV può avere un numero diverso di campi. L'attività è scrivere codice per generare quanti campi ci sono in ogni record del file. Puoi presumere che non ci sia una riga di intestazione nel file e che puoi leggere da un file o da un input standard, a tua scelta.

Puoi assumere una versione di rfc4180 per le regole CSV che spiegherò di seguito per la definizione di ogni riga del file. Ecco una versione leggermente modificata della parte pertinente delle specifiche:

Definizione del formato CSV

  1. Ogni record si trova su una riga separata, delimitata da un'interruzione di riga (CRLF). Per esempio:

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

  2. L'ultimo record nel file può avere o meno un'interruzione di riga finale. Per esempio:

    aaa,bbb,ccc CRLF
    zzz,yyy,xxx

(La regola 3. non si applica a questa sfida)

  1. All'interno di ogni record, ci possono essere uno o più campi, separati da virgole. Gli spazi sono considerati parte di un campo e non devono essere ignorati.

  2. Ogni campo può essere racchiuso tra virgolette doppie o meno. Se i campi non sono racchiusi tra virgolette doppie, le virgolette doppie potrebbero non apparire all'interno dei campi. Per esempio:

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

  3. I campi che contengono interruzioni di riga (CRLF), virgolette doppie e virgole devono essere racchiusi tra virgolette doppie. Per esempio:

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

  4. Se le virgolette doppie vengono utilizzate per racchiudere i campi, è necessario evitare una virgoletta doppia che appare all'interno di un campo precedendola con un'altra virgoletta doppia. Per esempio:

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

Esempio

Ingresso:

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

Dovrebbe dare l'output:

2, 3, 3, 5

Puoi fornire i valori di output nel modo che ritieni più conveniente.

biblioteche

Puoi usare qualsiasi libreria che ti piace.


Finora risposte fantastiche, ma ci manca una risposta da riga di comando / bash che sarebbe particolarmente interessante.

Risposte:


5

Stax , 19 12 byte

èJ§3‼}vAà○L>

Esegui ed esegui il debug

Disimballato, non golfato e commentato, sembra così.

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

Esegui questo


1
Come funziona?
Anush,

1
@Anush: ho aggiunto qualche informazione in più.
ricorsivo il

4

R , 40 byte

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

Provalo online!

Secondo la documentazione di count.fields, i campi con interruzioni di riga ottengono un conteggio dei campi di NA per la riga iniziale, quindi li filtriamo.


3

JavaScript (ES2018), 42 59 byte

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


Tecnicamente questo è ES2018 a causa della sbandiera sulla regex. Non che sia così importante ;-) E buon uso, a proposito!
ETHproductions

2
Questa funzione sembra funzionare solo su un record alla volta. Penso che la descrizione del problema richieda la gestione di un intero file di più record.
ricorsivo il

@ETHproductions, buon punto, verrà aggiornato.
Rick Hitchcock,

@recursive, hai ragione, ho frainteso gli input. Ora aggiornato, alla perdita di molti molti byte.
Rick Hitchcock,

3

Gelatina , 12 byte

ṣ”"m2FỴ=”,§‘

La risposta Stax di un porto ricorsivo : vai a dare credito!

Provalo online!

Come?

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

Forse preferisci ṣ”"m2ẎỴċ€”,‘- è stretto e ċ€conta le virgole in ciascuno.


2

Python, 63 byte

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

Restituisce l'output in un mapoggetto iterabile .


2
Utilizzando una lambdafunzione è possibile ottenere questo fino a 54 byte
ovs

@ovs Potrei non capire le regole ma il tuo TIO sembra aver precaricato l'input. È davvero valido?
Anush,

Vedo perché funziona ora (grazie solo a @ ASCII).
Anush,


2

Perl 5 , 10,0, 55 53 byte

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

Provalo online!

Spiegazione:

$_=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

2

Java 10, 101 byte

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

Provalo online.

Spiegazione:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.