Автоопределение наличия заголовков CSV в файле

Короткий вопрос: Как автоматически определить, есть ли в CSV файле заголовки в первой строке?

Подробности: я написал небольшой механизм синтаксического анализа CSV, который помещает данные в объект, к которому я могу получить доступ (приблизительно) базу данных в памяти. Первоначальный код был написан для анализа стороннего CSV с предсказуемым форматом, но я хотел бы иметь возможность использовать этот код в целом.

Я пытаюсь найти надежный способ автоматического обнаружения присутствия CSV-заголовков, поэтому script может решить, следует ли использовать первую строку CSV файла в виде имен ключей/столбцов или сразу же начать анализировать данные. Поскольку все, что мне нужно, является логическим тестом, я мог бы легко указать аргумент после проверки файла CSV сам, но мне бы не пришлось (идти на автоматизацию).

Я предполагаю, что мне придется разобрать первые 3? строки CSV файла и искать какой-то шаблон для сравнения с заголовками. У меня есть кошмары из трех особенно плохих случаев, в которых:

  • По некоторым причинам заголовки содержат числовые данные
  • Первые несколько строк (или большие части CSV) имеют значение null
  • Заголовки и данные выглядят слишком похожими, чтобы рассказать им обособленно.

Если я могу получить "лучшее предположение" и сбой анализатора с ошибкой или выплюнуть предупреждение, если он не может решить, что ОК. Если это то, что будет чрезвычайно дорогостоящим с точки зрения времени или вычисления (и займет больше времени, чем это должно было спасти меня), я с радостью откажусь от идеи и вернусь к работе над "важными вещами".

Я работаю с PHP, но это ставит меня скорее как алгоритмический/вычислительный вопрос, чем что-то конкретное. Если есть простой алгоритм, я могу использовать, отлично. Если вы можете указать мне на какую-то соответствующую теорию/дискуссию, это тоже здорово. Если есть гигантская библиотека, которая обрабатывает естественный язык или 300 различных видов разбора, мне это не интересно.

Ответ 1

Как указывали другие, вы не можете сделать это со 100% -ной надежностью. Бывают случаи, когда получение "в основном правильное" полезно, однако, например, инструменты таблиц с функциями импорта CSV часто пытаются понять это самостоятельно. Здесь несколько эвристик, которые будут указывать на первую строку, не являются заголовком:

  • Первая строка содержит столбцы, которые не являются строками или пустыми.
  • В столбцах первой строки не все уникальные
  • Первая строка содержит даты или другие общие форматы данных (например, xx-xx-xx)

Ответ 2

В самом общем смысле это невозможно. Это действительный файл csv:
Название
Джим
Том
Билл

Большинство читателей csv просто возьмут hasHeader в качестве опции и позволят вам передать свой собственный заголовок, если хотите. Даже в том случае, если вы считаете, что можете обнаружить, что являетесь символьными заголовками и числовыми данными, вы можете столкнуться с катастрофическим сбоем. Что, если ваша колонка - список серий BMW?
M
3
5
7

Вы обработаете это неправильно. Хуже всего, вы потеряете лучший автомобиль!

Ответ 3

В чисто абстрактном смысле, я не думаю, что есть надежный алгоритмический ответ на ваш вопрос, поскольку он сводится к следующему: "Как отличить dataA от dataB, если я ничего не знаю об одном из них?". Всегда будет потенциал для того, чтобы dataA был неотличим от dataB. Тем не менее, я бы начал с простой и единственной сложности при необходимости. Например, если рассматривать первые пять строк для данного столбца (или столбцов), если тип данных в строках 2-5 все одинаковы, но отличается от типа данных в строке 1, есть хороший шанс, что строка заголовка присутствует ( увеличенные размеры выборок уменьшают вероятность ошибки). Это могло бы (sorta) решить # 1/# 3 - возможно, выбросить исключение, если все строки заполнены, но данные неотличимы, чтобы позволить вызывающей программе решить, что делать дальше. Для # 2 просто не считайте строку как строку, пока и пока она не вытащит ненулевые данные..., которые будут работать во всех, кроме пустого файла (в этом случае вы попали бы в EOF). Это никогда не будет надежным, но может быть "достаточно близко".

Ответ 4

Это действительно зависит от того, насколько "общим" вы хотите, чтобы ваш инструмент был. Если данные всегда будут числовыми, вам будет легко, если вы принимаете нечисловые заголовки (что кажется довольно справедливым допущением).

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

FWIW, я на самом деле просто написал script для разбора некоторых вещей из TSV, все из одного источника. Исходный подход к заголовкам/форматированию был настолько разбросан, что имело смысл просто сделать script задавать мне вопросы из командной строки во время выполнения. (Это заголовок? Какие столбцы важны?). Так что нет автоматизации, но она позволяет мне летать через набор данных, над которыми я работаю, вместо того, чтобы предвидеть каждый забавный случай форматирования. Кроме того, мои ответы сохраняются в файле, поэтому я должен участвовать только один раз в файле. Не идеальный, но эффективный.

Ответ 5

Если у CSV есть заголовок, подобный этому.

Идентификатор, имя, адрес электронной почты, дата 1, john, [email protected], 12 jan 2020

Затем выполнение фильтра_var (str, FILTER_VALIDATE_EMAIL) в строке заголовка завершится с ошибкой. Поскольку адрес электронной почты находится только в данных строки. Поэтому проверьте строку заголовка для адреса электронной почты (если ваш CSV имеет в нем адреса электронной почты).

Вторая идея. http://php.net/manual/en/function.is-numeric.php Проверьте строку заголовка для is_numeric, скорее всего, строка заголовка не содержит числовых данных. Но, скорее всего, строка данных будет иметь числовые данные.

Если вы знаете, что у вас есть даты в ваших столбцах, то проверка строки заголовка для даты также будет работать.

Очевидно, вам нужно, какой тип данных вы ожидаете. Я "ожидаю" адреса электронной почты.