создание списков python «на лету» и их сравнение

#python #list #python-2.7 #set #comparison

#python #Список #python-2.7 #набор #сравнение

Вопрос:

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

Мой код выглядит так:

 sample_1=[]
sample_3=[]
sample_2=[]
sample_4=[]

for line in open("sample_EC1.Regions","r"):
    line=line.strip()
    sample_1.append(line)


for line in open("sample_EC2.Regions","r"):
    line=line.strip()
    sample_2.append(line)


for line in open("sample_EC3.Regions","r"):
    line=line.strip()
    sample_3.append(line)


for line in open("sample_EC4.Regions","r"):
    line=line.strip()
    sample_4.append(line)

CommonRegions = list(set(sample_2)amp;set(sample_3)amp;set(sample_4)amp;set(sample_1))

print CommonRegions
  

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

Комментарии:

1. for-циклы. функции. абстрагируйте свой жестко написанный код. СУХОЙ ( не повторяйтесь ).

Ответ №1:

 total=4

with open("sample_EC1.Regions","r") as f:
    commonregions = {line.strip() for line in f}

for i in range(2,total 1):
    with open("sample_EC" i ".Regions","r") as f:
        #set comprehension 
        sample = {line.strip() for line in f}
    commonregions = commonregions amp; sample

print commonregions
  

Вместо того, чтобы писать цикл for для каждого файла, попробуйте поместить их в цикл и выполнить пересечение.

улучшения:

  1. Два важных улучшения, во-первых, убедитесь, что вы снова закрываете файлы, а во-вторых, не преобразуете списки в наборы с избыточностью : with open(...) as f: s = {l.strip() for l in f} . Вещь с « for l in f » называется пониманием набора, «понимание набора» — это выражение, которое генерирует набор на лету

Комментарии:

1. Но имена файлов могут не совпадать каждый раз.

2. Два важных улучшения, во-первых, убедитесь, что вы снова закрываете файлы, а во-вторых, не преобразуете списки в наборы с избыточностью : with open(...) as f: s = {l.strip() for l in f} . Вещь с «для l в f» называется пониманием набора, на случай, если вам понадобится дополнительная информация.

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

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

5. Файл закрывается автоматически, поскольку он открывается в предложении with . Это должен быть способ открытия файлов по умолчанию, в противном случае вам понадобится try-catch-finally и close() там. Обратите внимание, что это не имеет значения для «коротких» программ, потому что ОС также автоматически закроет их, но у вас не может быть неограниченного количества открытых файлов, поэтому вы обычно хотите их повторно использовать. Тогда «понимание набора» — это выражение, которое генерирует набор «на лету». Вероятно, в Интернете вы найдете гораздо больше информации о понимании списков, но тогда понимание наборов является естественным расширением.

Ответ №2:

t — это список имен файлов

 b =[]

for fn in t:
    a=[]
    for line in open(fn,"r"):
        line=line.strip()
        a.append(line)
    b.append(set(a))

CommonRegions = set.intersection(*b)
print(CommonRegions)
  

Комментарии:

1. Добро пожаловать в SO! Хотя код в вашем ответе выглядит хорошо, всегда намного лучше добавить некоторые пояснения. Таким образом, будущим посетителям этого сайта будет легче находить информацию. Пояснения облегчают обучение. Поскольку ваш ответ не имеет объяснения, он появился в коде проверки на низкое качество.

2. Не накапливайте строки в списке, а затем не создавайте из него набор. Кроме того, если какая-либо операция завершается неудачно, происходит утечка открытого файла, что можно исправить, открыв его в предложении with . Единственным преимуществом этого является вызов to set.intersection() , с единственной оговоркой, что для этого требуется хотя бы один набор b .

Ответ №3:

Самый элегантный способ сделать это — использовать понимание списков и понимание наборов:

 def file_to_set(path):
    with open(path, "r") as f:
        return {line.strip() for line in f}

PATHS = ["sample_EC{0}.Regions".format(x) for x in range(1, 5)]

CommonRegions = set.intersection(*[file_to_set(path) for path in PATHS])

print CommonRegions
  

Спасибо @user3789032 за напоминание set.intersection .

С помощью этого вы можете установить PATHS любой набор файлов, которые вам нужно обработать. Если вы хотите прочитать пути в качестве параметров командной строки, используйте:

 import sys
PATHS = sys.argv[1:]
  

Если вы хотите прочитать пути из стандартного ввода:

 import sys
PATHS = [line.strip() for line in sys.stdin.readlines()]
  

Если вы хотите прочитать пути из файла, указанного в командной строке:

 import sys
with open(sys.argv[1]) as f:
    PATHS = [line.strip() for line in f]