Удаление кодов с почти одинаковыми значениями из списка кодов - Python - PullRequest
3 голосов
/ 14 апреля 2011

Я хочу очистить список диктов по следующим правилам:

1) Список диктов уже отсортирован, поэтому более ранние диктовки предпочтительнее.
2) В нижних диктантах, если строковые значения ['name'] и ['code'] совпадают с одинаковыми значениями ключа любого диктанта, находящегося выше в списке, и если абсолютное значение разности int(['cost']) между этими двумя диктовками < 2; тогда этот dict считается дубликатом предыдущего dict и удаляется из списка.

Вот один диктат из списка диктов:

{
'name':"ItemName", 
'code':"AAHFGW4S",
'from':"NDLS",
'to':"BCT",
'cost':str(29.95)
 }

Каков наилучший способ удаления дубликатов, подобных этому?

Ответы [ 3 ]

3 голосов
/ 14 апреля 2011

Может быть более питонический способ сделать это, но это основной псевдокод:

def is_duplicate(a,b):
  if a['name'] == b['name'] and a['cost'] == b['cost'] and abs(int(a['cost']-b['cost'])) < 2:
    return True
  return False

newlist = []
for a in oldlist:
  isdupe = False
  for b in newlist:
    if is_duplicate(a,b):
      isdupe = True
      break
  if not isdupe:
    newlist.append(a)
3 голосов
/ 14 апреля 2011

Поскольку вы говорите, что стоимость - целые числа, вы можете использовать это:

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) равны, поэтому вы можете использовать словарь для быстрого поиска всех кандидатов.

0 голосов
/ 14 апреля 2011

Вроде запутанная проблема, но я думаю, что-то вроде этого будет работать:

for i, d in enumerate(dictList):
    # iterate through the list of dicts, starting with the first
    for k,v in d.iteritems():
        # for each key-value pair in this dict...
        for d2 in dictList[i:]:
             # check against all of the other dicts "beneath" it
             # eg,
             # if d['name'] == d2['name'] and d['code'] == d2['code']:
             #     --check the cost stuff here--
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...