Comptez le nombre de champs dans chaque enregistrement csv

12

Imaginez un fichier texte dans lequel chaque enregistrement csv peut avoir différents nombres de champs. La tâche consiste à écrire du code pour afficher le nombre de champs dans chaque enregistrement du fichier. Vous pouvez supposer qu'il n'y a pas de ligne d'en-tête dans le fichier et pouvez lire à partir d'un fichier ou d'une entrée standard, comme vous le souhaitez.

Vous pouvez supposer une version de rfc4180 pour les règles csv que j'expliquerai ci-dessous pour la définition de chaque ligne du fichier. Voici une version légèrement modifiée de la partie pertinente de la spécification:

Définition du format CSV

  1. Chaque enregistrement est situé sur une ligne distincte, délimitée par un saut de ligne (CRLF). Par exemple:

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

  2. Le dernier enregistrement du fichier peut ou non avoir un saut de ligne de fin. Par exemple:

    aaa,bbb,ccc CRLF
    zzz,yyy,xxx

(La règle 3. ne s'applique pas dans ce défi)

  1. Dans chaque enregistrement, il peut y avoir un ou plusieurs champs, séparés par des virgules. Les espaces sont considérés comme faisant partie d'un champ et ne doivent pas être ignorés.

  2. Chaque champ peut ou non être placé entre guillemets. Si les champs ne sont pas entourés de guillemets doubles, les guillemets doubles peuvent ne pas apparaître à l'intérieur des champs. Par exemple:

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

  3. Les champs contenant des sauts de ligne (CRLF), des guillemets doubles et des virgules doivent être placés entre guillemets doubles. Par exemple:

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

  4. Si des guillemets doubles sont utilisés pour entourer des champs, un guillemet double apparaissant à l'intérieur d'un champ doit être échappé en le précédant d'un autre guillemet double. Par exemple:

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

Exemple

Contribution:

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

Devrait donner la sortie:

2, 3, 3, 5

Vous pouvez donner les valeurs de sortie de la manière qui vous convient le mieux.

Bibliothèques

Vous pouvez utiliser n'importe quelle bibliothèque que vous aimez.


Des réponses impressionnantes jusqu'à présent mais il nous manque une réponse en ligne de commande / bash qui serait particulièrement cool.

Anush
la source

Réponses:

5

Stax , 19 12 octets

èJ§3‼}vAà○L>

Exécuter et déboguer

Déballé, non golfé et commenté, il ressemble à ceci.

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

Exécutez celui-ci

récursif
la source
1
Comment ça marche?
Anush
1
@Anush: J'ai ajouté quelques informations supplémentaires.
récursif
4

R , 40 octets

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

Essayez-le en ligne!

Selon la documentation de count.fields, les champs avec des sauts de ligne obtiennent un nombre de champs NA pour la ligne initiale, nous les filtrons donc.

Giuseppe
la source
3

JavaScript (ES2018), 42 59 octets

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

Rick Hitchcock
la source
Techniquement, c'est ES2018 en raison du sdrapeau sur l'expression régulière. Ce n'est pas si important que ça ;-) Et bonne utilisation, btw!
ETHproductions
2
Cette fonction ne semble fonctionner que sur un seul enregistrement à la fois. Je pense que la description du problème nécessite la gestion d'un fichier entier de plusieurs enregistrements.
récursif
@ETHproductions, bon point, sera mis à jour.
Rick Hitchcock
@recursive, vous avez raison, j'ai mal compris les entrées. Maintenant mis à jour, à la perte de nombreux octets.
Rick Hitchcock
3

Gelée , 12 octets

ṣ”"m2FỴ=”,§‘

Un port de réponse récursive Stax - allez donner du crédit!

Essayez-le en ligne!

Comment?

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

Peut-être que vous préférez ṣ”"m2ẎỴċ€”,‘- est resserré et ċ€compte les virgules dans chacun.

Jonathan Allan
la source
2

Python, 63 octets

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

Renvoie la sortie dans un mapobjet itérable .

SlayerGames44
la source
2
En utilisant une lambdafonction, vous pouvez le réduire à 54 octets
ovs
@ovs Je ne comprends peut-être pas les règles, mais votre TIO semble avoir pré-préparé l'entrée. Est-ce vraiment valable?
Anush
Je vois pourquoi cela fonctionne maintenant (grâce à @ ASCII uniquement).
Anush
2

Perl 5 .10.0, 55 53 octets

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

Essayez-le en ligne!

Explication:

$_=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
la source
2

Java 10, 101 octets

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

Essayez-le en ligne.

Explication:

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
la source