2016-05-20 1 views
0

ディクテーション(例:d)があります。 dict.get(key, None)keydに存在しない場合はNoneを返します。Pythonで具体的な方法でキーのリストから最初の値を取得するにはどうすればよいですか?

は、どのように私はキーのリストから最初の値を(すなわち、d[key]Noneではありません)(そのうちのいくつかはdには存在しない可能性があります)を取得できますか?

このポストPythonic way to avoid “if x: return x” statementsは、具体的な方法を提供します。私はそれが動作

# a list of dicts 
list_dicts = [ {'level0' : (1, 2), 'col': '#ff310021'}, 
       {'level1' : (3, 4), 'col': '#ff310011'}, 
       {'level2' : (5, 6), 'col': '#ff312221'}] 

# loop over the list of dicts dicts, extract the tuple value whose key is like level* 
for d in list_dicts: 
    t = d.get('level0', None) or d.get('level1', None) or d.get('level2', None) 
    col = d['col'] 

    do_something(t, col) 

、で実証されたように、1行でそれをacheiveするXOR演算子を使用

for d in list_dicts: 
    for key in keys: 
     if key in d: 
      print(d[key]) 
      break 

。このように、私は単にすべてのオプション(level0level3)を記載しています。リスト内包のように、多くのキー(例えば、level0からlevel100まで)のためのより良い方法がありますか?

+0

@ user3100115、私は質問を編集し、あなたが言及した投稿を参照しました。私はそれが重複していないと信じています。 Plsはそれを再度チェックします。 – SparkAndShine

+0

この質問は基本的に元の(重複した)質問の特定のケースです。条件は 'd.get( 'level0'、None)'、 'd.get( 'level1'、None)'などです。 'check_size()'、 'check_color()'など –

答えて

4

この行を:

x, y = d.get('level0', None) or d.get('level1', None) or d.get('level2', None) 

です基本的にlist['level0', 'level1', 'level2']をにマッピングします(すでにNoneがデフォルト値です。この場合、明示的に状態を記述する必要はありません)。次に、基本的にフィルタであるNoneにマップされていないものを選択します。あなたは、組み込みの(Pythonの3で怠惰な発電機のようなオブジェクトである)機能map()filter()を使用して最初の試合を取得するためにnext()を呼び出すことができます。

list_dicts = [ {'level0' : (1, 2), 'col': '#ff310021'}, 
       {'level1' : (3, 4), 'col': '#ff310011'}, 
       {'level2' : (5, 6), 'col': '#ff312221'}] 
>>> l = 'level0', 'level1', 'level2' 
>>> for d in list_dicts: 
...  print(next(filter(None, map(d.get, l)))) 
... 
(1, 2) 
(3, 4) 
(5, 6) 
+3

'filter(None、...)'は "Nonesをフィルターにかける"という意味ではないことに注意してください。これは、 "ブール値として解釈されたときにfalseとみなされるものをフィルタにかける"ことを意味します。 – user2357112

+0

@ user2357112 - はい。私はそれがこのユースケースにとって望ましいと思う。 – TigerhawkT3

3

そこには便利な組み込みはませんが、あなたは簡単に十分な、それを実現することができます。

def getfirst(d, keys): 
    for key in keys: 
     if key in d: 
      return d[key] 
    return None 
1

を私は理解してnextを使用します。

# build list of keys 
levels = [ 'level' + str(i) for i in range(3) ] 

for d in list_dicts: 
    level_key = next(k for k in levels if d.get(k)) 
    level = d[level_key] 
1

は、すべてのニシキヘビで動作するはずです:

# a list of dicts 
list_dicts = [{'level0': (1, 2), 'col': '#ff310021'}, 
       {'level1': (3, 4), 'col': '#ff310011'}, 
       {'level2': (5, 6), 'col': '#ff312221'}] 

# Prioritized (ordered) list of keys [level0, level99] 
KEYS = ['level{}'.format(i) for i in range(100)] 


# loop over the list of dicts dicts, extract the tuple value whose key is 
# like level* 
for d in list_dicts: 
    try: 
     k = next(k for k in KEYS if k in d) 
     t = d[k] 
     col = d['col'] 

     do_something(t, col) 
    except StopIteration: 
     pass 
1

新規アイテムのように、ここではまず機能的構成を使ってゲッターを計算するバージョンがあります。

if 'reduce' not in globals(): 
    from functools import reduce 

list_dicts = [ {'level0' : (1, 2), 'col': '#ff310021'}, 
       {'level1' : (3, 4), 'col': '#ff310011'}, 
       {'level2' : (5, 6), 'col': '#ff312221'}] 


levels = list(map('level{}'.format, range(3))) 
getter = reduce(lambda f, key: lambda dct: dct.get(key, f(dct)), reversed(levels), lambda _: None) 

print(list(map(getter, list_dicts))) 

# [(1, 2), (3, 4), (5, 6)] 
関連する問題