Python - Преобразование длинного списка адресов в список строк и пересечение списков
У меня есть два очень длинных текстовых файла (тысячи адресов электронной почты, по одному на строку), и я ищу способ сравнить два файла и получить выходные данные с адресами, содержащимися в первом файле и во втором файле, но не в обоих (что-то вроде AUB/(A⋂B) в теории множеств). Было бы довольно легко, если бы я мог использовать списки, содержащие строки в качестве ввода, как это
input1=['address1','address2',...,'addressn']
но так как мой текстовый файл длинный и в разных строках, я должен вручную указывать каждый адрес среди ''. Поэтому я попытался использовать одну строку со всеми адресами, разделенными пробелом, в качестве входных данных, а затем преобразовать ее в список строк. Это то, что я вышел с:
import numpy as np
from StringIO import StringIO
def conv(data):
array1=np.genfromtxt(StringIO(data),dtype="|S50")
lista1=[]
for el in array1:
lista1.append(el)
return lista1
input1='address1 address2 ... addressn'
И это то, что я получаю, когда вызываю функцию
>conv(input1)
>['address1', 'address2', 'addressn']
Это работает, но у меня есть проблема: входные данные должны быть горизонтальными, поэтому я не могу скопировать свои адреса из текстового файла и вставить их в строку, как если бы я получил что-то вроде
input1="Davide
...:Michele
...:Giorgio
...:Paolo"
File "<ipython-input-4-6d70053fb94e>", line 1
input1="Davide
^
SyntaxError: EOL while scanning string literal
Как я могу решить эту проблему? Любое предложение по улучшению кода будет очень полезно. Я почти ничего не знаю о модуле StringIO, сегодня я впервые столкнулся с ним и уверен, что можно написать гораздо более эффективную программу, чем моя. Кстати, это вся программа:
def scan(data1,data2): #Strings
array1=np.genfromtxt(StringIO(data1),dtype="|S50")
array2=np.genfromtxt(StringIO(data2),dtype="|S50")
lista1=[]
lista2=[]
for el in array1:
lista1.append(el)
for el in array2:
lista2.append(el) #lista1 and lista2 are lists containing strings
num1,num2=len(lista1),len(lista2)
shared=[]
for el in lista1:
if el in lista2:
shared.append(el) #shared is the intersection of lista1 and lista2
if len(shared)==0:
print 'No shared elements'
return lista1+lista2
else:
for el in shared:
n1=lista1.count(el)
for i in range(n1):
lista1.remove(el) #Removes from lista1 the elements shared with lista2
n2=lista2.count(el) #as many times as they appear
for j in range(n2):
lista2.remove(el) #Removes from lista2 the elements shared with lista1
result=lista1+lista2 #as many times as they appear
print 'Addresses list 1:',num1
print 'Addresses list 2:',num2
print 'Useful Addresses:',len(list(set(result)))
return (list(set(result)))
и это пример того, как это работает:
data1="Davide John Kate Mary Susan"
data2="John Alice Clara Kate John Alex"
scan(data1,data2)
>Addresses list 1: 5
>Addresses list 2: 6
>Useful Addresses: 6
>['Alex', 'Susan', 'Clara', 'Alice', 'Mary', 'Davide']
Спасибо за помощь:)
3 ответа
Используйте тройные кавычки вокруг строки, охватывающей несколько строк:
input1="""Davide
...:Michele
...:Giorgio
...:Paolo"""
Затем они будут разделены по возвратам ("\n"
), чтобы вы могли использовать inpu1.split('\n')
превратить его в список.
Используя набор объектов, ваша работа становится довольно простой. Чтобы получить элементы в s1
которые не в s2
мы можем просто сделать s1 - s2
, Союз это просто |
и пересечение просто &
так все сказали у нас есть.
s1 = set(input1.split('\n'))
s2 = set(input2.split('\n'))
adresses_in_only_one_file = (s1 | s2) - (s1 & s2)
Расширяя ответ @irh, вы можете использовать sets
получить симметричную разницу между двумя наборами: (элементы в list1 и list2, но не в обоих)
list1 = ['address1', 'address2', 'address3']
list1 = ['address5', 'address4', 'address3']
result = list(set(list1) ^ set(list2))
>>> print result
['address1', 'address2', 'address4', 'address5'] #note result might be jumbled but that shouldn't matter
shared =[]
for el in lista1:
if el in lista2:
shared.append(el) #shared is the intersection of lista1 and lista2
In [10]: lista1=[1,2,3,4,5,6,7,8,9]
In [11]: lista2=[1,2,3,10,11,12,13]
In [12]: lista1=set(lista1)
In [13]: shared = lista1.intersection(lista2) # same as your loop above
In [14]: shared
Out[14]: {1, 2, 3}
Если вы хотите список, просто используйте list(lista1.intersection(lista2))
for el in shared:
n1=lista1.count(el)
for i in range(n1):
lista1.remove(el) #Removes from lista1 the elements shared with lista2
n2=lista2.count(el) #as many times as they appear
for j in range(n2):
lista2.remove(el)
result=lista1+lista2
lista1=set(lista1)
In [15]: list(lista1.symmetric_difference(lista2))
Out[15]: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13] # same as above.