Подсчитайте количество полей в каждой записи CSV

12

Представьте себе текстовый файл, где каждая запись CSV может иметь различное количество полей. Задача состоит в том, чтобы написать код для вывода количества полей в каждой записи файла. Вы можете предположить, что в файле нет строки заголовка и можете читать из файла или стандартного ввода, как вы выберете.

Вы можете принять версию rfc4180 для правил csv, которую я объясню ниже для определения каждой строки файла. Вот слегка отредактированная версия соответствующей части спецификации:

Определение формата CSV

  1. Каждая запись расположена на отдельной строке, разделенной разрывом строки (CRLF). Например:

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

  2. Последняя запись в файле может иметь или не иметь разрыв конца строки. Например:

    aaa,bbb,ccc CRLF
    zzz,yyy,xxx

(Правило 3. не применяется в этом вызове)

  1. В каждой записи может быть одно или несколько полей, разделенных запятыми. Пробелы считаются частью поля и не должны игнорироваться.

  2. Каждое поле может быть или не быть заключено в двойные кавычки. Если поля не заключены в двойные кавычки, то двойные кавычки могут не появляться внутри полей. Например:

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

  3. Поля, содержащие разрывы строк (CRLF), двойные кавычки и запятые, должны быть заключены в двойные кавычки. Например:

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

  4. Если двойные кавычки используются для включения полей, то двойная кавычка, появляющаяся внутри поля, должна быть экранирована, предшествуя другой двойной кавычке. Например:

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

пример

Входные данные:

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

Должен дать вывод:

2, 3, 3, 5

Вы можете указать выходные значения любым удобным для вас способом.

Библиотеки

Вы можете использовать любую библиотеку, которая вам нравится.


Потрясающие ответы до сих пор, но нам не хватает ответа командной строки / bash, который был бы особенно клевым.

Ануш
источник

Ответы:

5

Stax , 19 12 байт

èJ§3‼}vAà○L>

Запустите и отладьте его

Распакованный, размазанный и прокомментированный, это выглядит так.

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

Запустите этот

рекурсивный
источник
1
Как это работает?
Ануш
1
@Anush: я добавил еще немного информации.
рекурсивный
3

JavaScript (ES2018), 42 59 байт

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

Рик Хичкок
источник
Технически это ES2018 из-за sфлага на регулярном выражении. Не то, чтобы это имело такое большое значение ;-) И хорошее использование этого, кстати!
ETHproductions
2
Эта функция работает только для одной записи за раз. Я думаю, что описание проблемы требует обработки всего файла из нескольких записей.
рекурсивный
@ETHproductions, хороший момент, будет обновлять.
Рик Хичкок
@ recursive, вы правы, я неправильно понял входные данные. Сейчас обновляется, при потере много- много байтов.
Рик Хичкок
3

Желе , 12 байт

ṣ”"m2FỴ=”,§‘

Порт Stax ответ рекурсивного - иди кредит!

Попробуйте онлайн!

Как?

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

Может быть, вы предпочитаете ṣ”"m2ẎỴċ€”,‘- это затянуть и ċ€считать запятые в каждом.

Джонатан Аллан
источник
2

Python, 63 байта

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

Возвращает вывод в итерируемом mapобъекте.

SlayerGames44
источник
2
Используя lambdaфункцию, вы можете уменьшить это до 54 байтов
ovs
@ovs Возможно, я не понимаю правила, но ваш TIO, кажется, подготовил ввод. Это действительно верно?
Ануш
Теперь я понимаю, почему это работает (благодаря @ ASCII-only).
Ануш
2

Perl 5 .10.0, 55 53 байта

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

Попробуйте онлайн!

Объяснение:

$_=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
источник
2

Java 10, 101 байт

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

Попробуйте онлайн.

Объяснение:

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
Кевин Круйссен
источник