Как вы динамически идентифицируете неизвестные разделители в файле данных?

У меня есть три файла входных данных. Каждый из них использует другой разделитель для содержащихся в нем данных. Файл данных выглядит так:

  яблоки |  бананы |  апельсины |  виноград 

файл данных два выглядит следующим образом:

  четверть, копейка, никель, пенни 

файл данных три выглядит следующим образом:

  корова корова свинья куриная коза 

(изменение количества столбцов также является преднамеренным)

Мысль, которую я имел, состояла в том, чтобы подсчитать количество символов, отличных от альфы, и предположить, что самый высокий счетчик был символом разделителя. Тем не менее, файлы с не-пространственными разделителями также имеют пробелы до и после разделителей, поэтому пробелы выигрывают во всех трех файлах. Вот мой код:

def count_chars(s): valid_seps=[' ','|',',',';','\t'] cnt = {} for c in s: if c in valid_seps: cnt[c] = cnt.get(c,0) + 1 return cnt infile = 'pipe.txt' #or 'comma.txt' or 'space.txt' records = open(infile,'r').read() print count_chars(records) 

Он будет печатать словарь с подсчетом всех допустимых символов. В каждом случае пространство всегда побеждает, поэтому я не могу полагаться на это, чтобы сообщить мне, что такое разделитель.

Но я не могу придумать лучшего способа сделать это.

Какие-либо предложения?

    3 Solutions collect form web for “Как вы динамически идентифицируете неизвестные разделители в файле данных?”

    Если вы используете python, я бы предложил просто вызвать re.split в строке со всеми допустимыми ожидаемыми разделителями:

     >>> l = "big long list of space separated words" >>> re.split(r'[ ,|;"]+', l) ['big', 'long', 'list', 'of', 'space', 'separated', 'words'] 

    Единственная проблема заключается в том, что если один из файлов использовал разделитель как часть данных.

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

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

    Как насчет того, чтобы попробовать стандарт Python CSV: http://docs.python.org/library/csv.html#csv.Sniffer

     import csv sniffer = csv.Sniffer() dialect = sniffer.sniff('quarter, dime, nickel, penny') print dialect.delimiter # returns ',' 

    Я закончил с регулярным выражением из-за проблемы пространств. Вот мой готовый код, на случай, если кто-то заинтересован, или может использовать что-нибудь еще в нем. По касательной ноте было бы аккуратно найти способ динамически идентифицировать порядок столбцов, но я понимаю, что это немного сложнее. Тем временем я отказываюсь от старых трюков, чтобы разобраться в этом.

     for infile in glob.glob(os.path.join(self._input_dir, self._file_mask)): #couldn't quite figure out a way to make this a single block #(rather than three separate if/elifs. But you can see the split is #generalized already, so if anyone can come up with a better way, #I'm all ears!! :) for row in open(infile,'r').readlines(): if infile.find('comma') > -1: datefmt = "%m/%d/%Y" last, first, gender, color, dobraw = \ [x.strip() for x in re.split(r'[ ,|;"\t]+', row)] elif infile.find('space') > -1: datefmt = "%m-%d-%Y" last, first, unused, gender, dobraw, color = \ [x.strip() for x in re.split(r'[ ,|;"\t]+', row)] 
    elif infile.find('pipe') > -1: datefmt = "%m-%d-%Y" last, first, unused, gender, color, dobraw = \ [x.strip() for x in re.split(r'[ ,|;"\t]+', row)] #There is also a way to do this with csv.Sniffer, but the #spaces around the pipe delimiter also confuse sniffer, so #I couldn't use it. else: raise ValueError(infile + "is not an acceptable input file.")

    Python - лучший язык программирования в мире.