2017-05-05 10 views
1

どのようにコードを変更して1つのループだけを使うことができますか?私は...など.iteritems()、iterkeys()を使用しようPython - 多次元辞書をループするためのより良い方法

for user in data: 
    for item in data[user]: 
     start = seconds_since_midnight(
      data[user][item]['start'] 
     ) 
     end = seconds_since_midnight(
      data[user][item]['end'] 
     ) 
     overtime = end - start 

     if overtime > eight_hours: 
      if user not in result: 
       if str(user) not in names.keys(): 
        continue 
       result[user] = { 
        'name': names[str(user)]['name'], 
        'overtime': [] 
       } 

      result[user]['overtime'].append(overtime - eight_hours) 
    try: 
     result[user]['overtime'] = sum(result[user]['overtime']) 
    except KeyError: 
     pass 

return sorted(
    result.items(), 
    key=lambda result: result[1]['overtime'], 
    reverse=True 
) 

それは、このような構造を作成します。 データ= { 'のuser_id':{ datetime.date(2013、10、 1):{ 'start':datetime.time(9,0,0)、 'end':datetime.time(17,30,0)、 }、 datetime.date(2013、10、2) :{ 'start':datetime.time(8,30,0)、 'end':datetime.time(16,45,0)、 }、 } }

+1

を行う機能

def condition_new(user, total_overtime_): return str(user) in names and total_overtime_ > 0 def comp_hours_new_new(user, total_overtime_): return {'name': names[str(user)]['name'], 'overtime': total_overtime_} 

を紹介します。私が知る限り、あなたはすべての要素に一度アクセスします。したがって、並列スレッド/プロセスで作業を実行する予定がない限り、1つのループのみを使用することでほとんど利益が得られません。 – JohanL

+1

質問者は、「フラットが入れ子に比べて優れている」という事実によって動機づけられるかもしれません。 (Zen of Python) –

答えて

2

最初に発言することは、辞書であるためdataに一度しか出現しないとみなすことができます。

ソリューション1

今これらの2つの機能を紹介:

def overtime(item): 
    start = seconds_since_midnight(item['start']) 
    end = seconds_since_midnight(item['end']) 

    return end - start 


def comp_hours(name, items): 
    return {'name': name, 
      'overtime': sum(overtime(item) - 8 for item in items if overtime(item) > 8)} 

は今、この辞書理解を行います

result = {u: comp_hours(names[str(u)]['name'], i) for u, i in data.items() if str(u) in names} 
result_filtered = {k: v for k, v in result.items() if v > 0} 

あなたは、ソートを自分で行う必要があります。

ソリューション2

我々は、我々の最初のソリューションを変更します。

def total_overtime(items): 
    return sum(overtime(item) - 8 for item in items if overtime(item) > 8) 


def comp_hours_new(user, items): 
    return {'name': names[str(user)]['name'], 'overtime': total_overtime(items)} 


def condition(user, items): 
    return str(user) in names and total_overtime(items) > 0 

次に、関数型プログラミングでは、この

{u: comp_hours_new(u, i) for u, i in data.items() if condition(u, i)} 

を行うあなたはtotal_overtimeovertime 2Xを計算する必要はないだろうな機能を紹介します。

すべてこの1は我々のソリューションビットを変更して、発電機で動作するCPU時間を消耗(waisting)克服するために、このパターン

{k: f(k, v) for k, v in your_dict.items() if condition(k, v)} 

ソリューション3

の古典的なケースだった後。 は、あなたが唯一のループを持つようにしたいのはなぜ今

I = ((u, total_overtime(i)) for u, i in data.items()) 
{u: comp_hours_new_new(u, ttl_over) for u, ttl_over in I if condition_new(u, ttl_over)} 
+0

私はあなたのソリューションを使いました。ありがとう! –

+1

@DamianWysocki残業をしていないユーザーをフィルタリングすることを忘れてしまったが、私はそれを修正した。あなたは別の顔をしたい。 – Elmex80s

+1

あなたのソリューションに感謝してくれてありがとうございます;) –

関連する問題