Поскольку вы говорите, что стоимость - целые числа, вы можете использовать это:
def neardup( items ):
forbidden = set()
for elem in items:
key = elem['name'], elem['code'], int(elem['cost'])
if key not in forbidden:
yield elem
for diff in (-1,0,1): # add all keys invalidated by this
key = elem['name'], elem['code'], int(elem['cost'])-diff
forbidden.add(key)
Вот менее хитрый способ, который действительно рассчитывает разницу:
from collections import defaultdict
def neardup2( items ):
# this is a mapping `(name, code) -> [cost1, cost2, ... ]`
forbidden = defaultdict(list)
for elem in items:
key = elem['name'], elem['code']
curcost = float(elem['cost'])
# a item is new if we never saw the key before
if (key not in forbidden or
# or if all the known costs differ by more than 2
all(abs(cost-curcost) >= 2 for cost in forbidden[key])):
yield elem
forbidden[key].append(curcost)
Оба решения избегают повторного сканированияцелый список для каждого элемента.В конце концов, стоимость становится интересной, только если (name, code)
равны, поэтому вы можете использовать словарь для быстрого поиска всех кандидатов.