2015-10-02 17 views
7

Mam listę słowników nieaktualne obiektów:Jak uprościć listę słowników według stanu?

{ "begin" :date object1, "end" : date object2 } 
.... 
{ "begin" :date object3, "end" : date object4 } 

chcę upraszczać tej listy Stan:

if cur.end == next.begin - datetime.timedelta(seconds=1)) 
    cur.end = next.end 
    delete next 

Jak to zrobić?

+0

A jak byś uprościć ostatni? –

+1

http://stackoverflow.com/questions/5434891/iterate-a-list-as-pair-current-next-in-python –

+1

to ci bardzo pomoże. również iteruj na kopii tej listy, w przeciwnym razie nie możesz usunąć następnego podczas iterowania listy ;-) –

Odpowiedz

1

Używam liczb całkowitych zamiast obiektów datetime, aby zachować prosty kod, ale jest to banalne, aby zmienić go na potrzeby. Usuwanie elementów z kolekcji podczas iteracji spowoduje przerwanie iteratora, więc albo użyjesz drugiej listy (może to być intensywna pamięć) albo zastąpisz elementy zamiast ich kasować. Ponieważ twoje elementy to słowniki, pomyślałem, że można bezpiecznie zastąpić element, który ma zostać usunięty, brakiem, a na końcu odfiltrować Nones.

l=[ 
{ "b" : 1, "e" : 2}, 
{ "b" : 3, "e" : 5}, 
{ "b" : 6, "e" : 7}, 
{ "b" : 10, "e" : 12}, 
{ "b" : 13, "e" : 20} 
] 

for i in xrange(len(l) - 1): 
    cur = l[i] 
    if not cur: 
     continue 
    next = l[i + 1] 
    if cur["e"] == next["b"] - 1: 
     cur["e"] = next["e"] 
     l[i+1] = None 

l = filter(None, l) 
print l 

Ponieważ pierwsza wersja nie spełnia Twoich wymagań, powtórz te czynności, dopóki nie zostaną scalone żadne interwały czasowe. Jest to nieefektywne i prawdopodobnie najbardziej niepietonowe fragmenty kodu dzisiaj, ale spełnia swoją rolę.

changed = True 
while changed: 
    changed = False 
    l = filter(None, l) 
    for i in xrange(len(l) - 1): 
     cur = l[i] 
     if cur is None: 
      continue 
     next = l[i + 1] 
     if cur["e"] == next["b"] - 1: 
      cur["e"] = next["e"] 
      l[i+1] = None 
      changed = True 

l = filter(None, l) 
print l 
+0

wynikiem musi być [{'b': 1, 'e': 7}, {'b': 10, 'e ": 20}, {'b': 22, 'e': 24}], nie [{'b': 1, 'e': 5}, {'b': 6, 'e': 7}, {'b': 10, 'e': 20}, {'b': 22, 'e': 24}] – Bdfy

+0

@Bdfy Nie wiem, gdzie jest {'b': 22, 'e': 24 } pochodzić z. Nie widzę tego w moich wynikach – user1514631

1

Jak wyjaśniono w drugiej odpowiedzi, nie należy usunąć element z listy podczas iteracji nad nim, może to prowadzić do wielu problemów. Inna metoda, która tworzy całkowicie nową listę będzie -

import datetime 
lisdic = [] #list of dictionaries 
prev = None 
result = [] 
for i in lisdic: 
    if not prev: 
     prev = i 
    elif prev['end'] == i['begin'] - datetime.timedelta(seconds=1): 
     prev['end'] = i['end'] 
    else: 
     result.append(prev) 
     prev = i 
if prev: 
    result.append(prev) 

to również uchwyt podobnych odstępach czasu w wielu słowników (przykładem jest 3 pierwsze słowniki na liście w demo poniżej).

Demo -

>>> import datetime 
>>> lisdic = [{"begin":datetime.datetime(2015,10,2,10,0,0),"end":datetime.datetime(2015,10,2,10,30,0)}, 
... {"begin":datetime.datetime(2015,10,2,10,30,1),"end":datetime.datetime(2015,10,2,11,0,0)}, 
... {"begin":datetime.datetime(2015,10,2,11,0,1),"end":datetime.datetime(2015,10,2,12,0,0)}, 
... {"begin":datetime.datetime(2015,10,3,10,0,0),"end":datetime.datetime(2015,10,3,10,30,0)}, 
... {"begin":datetime.datetime(2015,10,3,11,0,0),"end":datetime.datetime(2015,10,3,11,30,0)}, 
... {"begin":datetime.datetime(2015,10,4,12,0,0),"end":datetime.datetime(2015,10,2,12,10,0)}] 
>>> prev = None 
>>> result = [] 
>>> for i in lisdic: 
...  if not prev: 
...   prev = i 
...  elif prev['end'] == i['begin'] - datetime.timedelta(seconds=1): 
...   prev['end'] = i['end'] 
...  else: 
...   result.append(prev) 
...   prev = i 
... 
>>> 
>>> if prev: 
...  result.append(prev) 
... 
>>> pprint.pprint(result) 
[{'begin': datetime.datetime(2015, 10, 2, 10, 0), 
    'end': datetime.datetime(2015, 10, 2, 12, 0)}, 
{'begin': datetime.datetime(2015, 10, 3, 10, 0), 
    'end': datetime.datetime(2015, 10, 3, 10, 30)}, 
{'begin': datetime.datetime(2015, 10, 3, 11, 0), 
    'end': datetime.datetime(2015, 10, 3, 11, 30)}, 
{'begin': datetime.datetime(2015, 10, 4, 12, 0), 
    'end': datetime.datetime(2015, 10, 2, 12, 10)}] 
Powiązane problemy