Cuente el número de campos en cada registro csv


12

Imagine un archivo de texto donde cada registro csv puede tener diferentes números de campos. La tarea es escribir código para generar cuántos campos hay en cada registro del archivo. Puede suponer que no hay una línea de encabezado en el archivo y puede leer desde un archivo o entrada estándar, según lo elija.

Puede asumir una versión de rfc4180 para las reglas csv que explicaré a continuación para la definición de cada línea del archivo. Aquí hay una versión ligeramente editada de la parte relevante de la especificación:

Definición del formato CSV

  1. Cada registro está ubicado en una línea separada, delimitada por un salto de línea (CRLF). Por ejemplo:

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

  2. El último registro en el archivo puede o no tener un salto de línea final. Por ejemplo:

    aaa,bbb,ccc CRLF
    zzz,yyy,xxx

(La regla 3. no se aplica en este desafío)

  1. Dentro de cada registro, puede haber uno o más campos, separados por comas. Los espacios se consideran parte de un campo y no se deben ignorar.

  2. Cada campo puede estar o no encerrado entre comillas dobles. Si los campos no están encerrados entre comillas dobles, entonces las comillas dobles pueden no aparecer dentro de los campos. Por ejemplo:

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

  3. Los campos que contienen saltos de línea (CRLF), comillas dobles y comas deben ir entre comillas dobles. Por ejemplo:

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

  4. Si se usan comillas dobles para encerrar campos, entonces se debe escapar una comilla doble que aparece dentro de un campo precediéndola con otra comilla doble. Por ejemplo:

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

Ejemplo

Entrada:

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

Debería dar la salida:

2, 3, 3, 5

Puede proporcionar los valores de salida de la forma que le resulte más conveniente.

Bibliotecas

Puedes usar cualquier biblioteca que quieras.


Respuestas impresionantes hasta ahora, pero nos falta una respuesta de línea de comando / bash que sería particularmente genial.

Respuestas:


5

Stax , 19 12 bytes

èJ§3‼}vAà○L>

Ejecutar y depurarlo

Desempaquetado, sin golf y comentado, se ve así.

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

Ejecute este


1
¿Como funciona?
Anush

1
@Anush: he agregado más información.
recursivo

4

R , 40 bytes

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

Pruébalo en línea!

Según la documentación de count.fields, los campos con saltos de línea obtienen un recuento de campos de NA para la línea inicial, por lo que los filtramos.


3

JavaScript (ES2018), 42 59 bytes

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


Técnicamente, esto es ES2018 debido a la sbandera en la expresión regular. No es que importe tanto ;-) ¡Y buen uso, por cierto!
ETHproductions

2
Esta función solo parece funcionar en un registro a la vez. Creo que la descripción del problema requiere manejar un archivo completo de múltiples registros.
recursivo

@ETHproductions, buen punto, se actualizará.
Rick Hitchcock

@recursivo, tienes razón, no entendí las entradas. Ahora actualizado, con la pérdida de muchos muchos bytes.
Rick Hitchcock

3

Jalea , 12 bytes

ṣ”"m2FỴ=”,§‘

La respuesta Stax de un puerto recursivo : ¡ve a dar crédito!

Pruébalo en línea!

¿Cómo?

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

Tal vez prefiera ṣ”"m2ẎỴċ€”,‘: es apretar y ċ€cuenta las comas en cada uno.


2

Python, 63 bytes

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

Devuelve la salida en un mapobjeto iterable .


2
Usando una lambdafunción puede reducir esto a 54 bytes
ovs

@ovs Puede que no entienda las reglas, pero su TIO parece haber preparado previamente la entrada. ¿Es eso realmente válido?
Anush

Veo por qué funciona ahora (gracias solo a @ ASCII).
Anush


2

Perl 5 .10.0, 55 53 bytes

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

Pruébalo en línea!

Explicación:

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

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

Pruébalo en línea.

Explicación:

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.