Используйте модифицированный N / K-способ сортировки , который обрабатывает весь набор файлов сравнения за проход.Только подсчет и продвижение должны быть сделаны;Сама часть объединения может быть пропущена.
При этом используется тот факт, что входные данные уже отсортированы.Если они еще не отсортированы, сортируйте их и сохраняйте на отсортированном диске :-) Пусть ваши друзья сохранят файловые буферы операционной системы и упреждают чтение.
Счастливое кодирование.
С помощьюнемного хитрости Я считаю, что это также можно расширить, чтобы указать разницу в процентах между всеми файлами за один проход.Просто нужно отслеживать «запаздывающий» вход и счетчики для каждого набора отношений (мм против 1-м).
Код спойлера, который, кажется, работает для меня на данных, представленных в вопросе..
Конечно, я не проверял это на действительно больших файлах или, вообще, вообще."Это бежало".Определение «уникальный» выше было проще, чем я изначально думал, поэтому некоторые из предыдущих ответов не имеют большого значения.Этот код далек от совершенства.Используйте на свой страх и риск (как от взрыва компьютера, так и от скуки / отвращения, чтобы не провернуть что-то лучше!).Работает на Python 3.1.
import os
import itertools
# see: http://docs.python.org/dev/library/itertools.html#itertools-recipes
# modified for 3.x and eager lists
def partition(pred, iterable):
t1, t2 = itertools.tee(iterable)
return list(itertools.filterfalse(pred, t1)), list(filter(pred, t2))
# all files here
base = "C:/code/temp"
names = os.listdir(base)
for n in names:
print("analyzing {0}".format(n))
# {name => file}
# files are removed from here as they are exhausted
files = dict([n, open(os.path.join(base,n))] for n in names)
# {name => number of shared items in any other list}
shared_counts = {}
# {name => total items this list}
total_counts = {}
for n in names:
shared_counts[n] = 0
total_counts[n] = 0
# [name, currentvalue] -- remains mostly sorted and is
# always a very small n so sorting should be lickity-split
vals = []
for n, f in files.items():
# assumes no files are empty
vals.append([n, str.strip(f.readline())])
total_counts[n] += 1
while len(vals):
vals = sorted(vals, key=lambda x:x[1])
# if two low values are the same then the value is not-unique
# adjust the logic based on definition of unique, etc.
low_value = vals[0][1]
lows, highs = partition(lambda x: x[1] > low_value, vals)
if len(lows) > 1:
for lname, _ in lows:
shared_counts[lname] += 1
# all lowest items discarded and refetched
vals = highs
for name, _ in lows:
f = files[name]
val = f.readline()
if val != "":
vals.append([name, str.strip(val)])
total_counts[name] += 1
else:
# close files as we go. eventually we'll
# dry-up the 'vals' and quit this mess :p
f.close()
del files[name]
# and what we want...
for n in names:
unique = 1 - (shared_counts[n]/total_counts[n])
print("{0} is {1:.2%} unique!".format(n, unique))
Ретроспективно я уже вижу недостатки!:-) Сортировка vals
происходит по устаревшей причине, которая больше не применяется.Практически просто min
будет работать нормально (и, вероятно, будет лучше для любого относительно небольшого набора файлов).