2016-02-05 2 views
0

Мне регулярно нужно считывать данные из (обычно с разделителями) значений и преобразовывать их в dicts. Обычно мне просто нужно сопоставить один из столбцов с другим, но может быть некоторая обработка значений (например, удаление дескрипторов). Я пытался придумать образец понимания речи, чтобы сделать это, но я все время сталкиваюсь с небольшими неприятностями, которые мешают мне реализовать его наиболее кратким и понятным способом. И я чувствую, что, вероятно, лучший способ.Чтение из файла с использованием определений dict.

Так вот (некоторые) способами, которые я попробовал, и куда они пошли не так:


 
with open(path) as f: 
    return {line.split("\t")[0].strip(): line.split("\t")[1].strip() 
      for line in f} 

Это то, что я часто в конечном итоге использование. Это позволяет мне модифицировать ключ и значение на месте и работать с любым из столбцов (например, если бы я хотел отображать значения из третьего в первый столбец). Очевидной проблемой является дублирование части line.split(). Есть ли способ привязать line.split("\t") к временной переменной или распаковать значения непосредственно в переменные?


 
with open(path) as f: 
    return dict(line.split("\t")[:2] for line in f) 

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


 
d = dict() 
for line in open(path): 
    d.update({line.split("\t")[0]: line.split("\t")[1]}) 
return d 

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


Я также играл с вложенным Dict постижений и распаковками расщепленных строк в переменные, но столкнулся с различными проблемами с этим.

+0

Вы пытаетесь оптимизировать что-то, что, вероятно, связано с вводом-выводом, поэтому ничего не делать с созданием словарей как быстро или wi что наименьшее количество кода, вероятно, сильно изменит ситуацию. – martineau

ответ

0

Вы можете сортировать сделать это, поставив что-то вокруг вашего f:

def tabsplit(file_object): 
    for line in file_object: 
     yield line.split("\t") 

А потом:

with open(path) as f: 
    return {left.strip(): right.strip() for left, right, *rest in tabsplit(f)} 
+0

Интересно, я не пробовал использовать генераторы каким-либо образом ... Тем не менее, здесь возникают проблемы с распаковкой, которые я намекнул ранее. Входные файлы могут содержать разное количество вкладок - например, могут быть конечные значения, принадлежащие последнему столбцу. Эти файлы затем будут бросать ValueError, который я не знаю, как обращаться с пониманием dict. Обычно файлы также содержат другие столбцы, которые не обязательно должны быть в dict, игнорируя их, распаковывая их в _, _, ... возможно, но я не считаю это слишком элегантным. –

+0

Итак, вы хотите игнорировать каждый столбец, за исключением первых двух? См. Мое редактирование, чтобы выбросить '* rest'. – L3viathan

+0

Удивительно, спасибо! –

0

Не уверен, почему создание словаря первый не будет работать

result = {} 
with open(path) as f: 
    for line in f: 
     columns = line.split("\t") 
     key = columns[0] # first item is the key right? 
     result[key] = columns[1] 
+0

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

+1

@ Себастиан: Короче не всегда == лучше. Читаемость и ремонтопригодность очень важны, и эффективность часто не имеет значения ... как в 97% случаев. См. [_When to optimize_] (https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize). – martineau

+0

@martineau Я знаю, именно поэтому я задаю этот вопрос. Поиск кода кода, который я всегда могу использовать для этого, позволит мне использовать его последовательно, тем самым увеличивая ремонтопригодность и понятность в долгосрочной перспективе. И если я смогу найти шаблон с меньшим количеством строк, я бы предпочел бы это просто потому, что это меньше прокрутки - я, как правило, работаю в ноутбуке IPython, а дополнительные строки складываются довольно быстро ... –

Смежные вопросы