Bir dikte listesinden değer listesi alma


184

Bunun gibi diktelerin bir listesi var:

[{'value': 'apple', 'blah': 2}, 
 {'value': 'banana', 'blah': 3} , 
 {'value': 'cars', 'blah': 4}]

İstiyorum ['apple', 'banana', 'cars']

Bunu yapmanın en iyi yolu nedir?

Yanıtlar:


324

Her diktenin bir valueanahtarı olduğunu varsayarsak, yazabilirsiniz (listenizin ismini varsayarak l)

[d['value'] for d in l]

Eğer valueeksik olabilir, kullanabilirsiniz

[d['value'] for d in l if 'value' in d]

8
Bir anahtarın eksik değerini tedavi etmek için, d.get ("key_to_lookup", "alternate_value") da kullanılabilir. Sonra şöyle görünecektir: [l cinsinden d için d.get ('değer', 'alt')]. Değer anahtar olarak mevcut değilse, sadece 'alt' döndürür.
abhinav

Çözüm için teşekkürler
Ajay Kumar

Bu "sihir" liste anlama olarak bilinir docs.python.org/3/tutorial/…
William Ardila

34

Map () ve lambda işlevlerini kullanarak bunu yapmanın başka bir yolu:

>>> map(lambda d: d['value'], l)

burada l listedir. Bu şekilde "en seksi" görüyorum, ama bunu liste kavrayışını kullanarak yapardım.

Güncelleme: Anahtar değerin 'değer' eksik olması durumunda:

>>> map(lambda d: d.get('value', 'default value'), l)

Güncelleme: Ben de lambdasların büyük bir hayranı değilim, bir şeyleri adlandırmayı tercih ediyorum ... bunu akılda tutarak şöyle yaparım:

>>> import operator
>>> map(operator.itemgetter('value'), l)

Hatta daha ileri gitmek ve açıkça ne elde etmek istediğini söyleyen tek bir işlev oluşturmak:

>>> import operator, functools
>>> get_values = functools.partial(map, operator.itemgetter('value'))
>>> get_values(l)
... [<list of values>]

Python 3 ile, mapbir yineleyici döndürdüğünden, listbir liste döndürmek için kullanın , örn list(map(operator.itemgetter('value'), l)).


1
Brüt! Liste kavrayışı burada çok daha mantıklı.
Mike Graham

4
İlkini mapkullanacaksanız operator.itemgetter('value'), değil , kullanın lambda.
agf

18
[x['value'] for x in list_of_dicts]

veya dict_list'deki d için [d.getkey ('değer')]
rplnt

1
@rpInt Um, böyle bir şey getkeyyok .. yani d.get('value')? Bu, isbadawi'nin Michal'in değil 2. liste kavrayışıyla aynı olurdu.
agf

3
Evet, üzgünüm, demek istedim. Anahtar eksikse istisna atmayacak bir şey demek istedim. Ancak @ isbadawi'nin çözümü, anahtar eksik olduğunda get () işlevinin None (veya varsayılan olarak belirttiğimiz her şeyi) sağlayacağı için daha iyidir.
rplnt

5

Bunun gibi çok basit bir durum için, İsmail Badawi'nin cevabında olduğu gibi bir anlayış kesinlikle gidilecek yoldur.

Ancak işler daha karmaşık hale geldiğinde ve içlerinde karmaşık ifadelerle çok yanlı veya iç içe anlayışlar yazmaya başlamanız gerektiğinde, diğer alternatiflere bakmaya değer. JSONPath, DPath ve KVC gibi iç içe geçmiş ve liste yapılarında XPath stili aramaları belirtmenin birkaç farklı (yarı) standart yolu vardır. Ve onlar için PyPI'de güzel kütüphaneler var.

Kitaplık adında dpath, biraz daha karmaşık bir şeyi nasıl basitleştirebileceğini gösteren bir örnek :

>>> dd = {
...     'fruits': [{'value': 'apple', 'blah': 2}, {'value': 'banana', 'blah': 3}],
...     'vehicles': [{'value': 'cars', 'blah':4}]}

>>> {key: [{'value': d['value']} for d in value] for key, value in dd.items()}
{'fruits': [{'value': 'apple'}, {'value': 'banana'}],
 'vehicles': [{'value': 'cars'}]}

>>> dpath.util.search(dd, '*/*/value')
{'fruits': [{'value': 'apple'}, {'value': 'banana'}],
 'vehicles': [{'value': 'cars'}]}

Veya jsonpath-ng:

>>> [d['value'] for key, value in dd.items() for d in value]
['apple', 'banana', 'cars']
>>> [m.value for m in jsonpath_ng.parse('*.[*].value').find(dd)]
['apple', 'banana', 'cars']

Bu, ilk bakışta o kadar basit görünmeyebilir, çünkü finddoğrudan eşleşen değerin yanı sıra her öğeye doğrudan bir yol gibi her türlü şeyi içeren eşleşme nesneleri döndürür. Ancak daha karmaşık ifadeler '*.[*].value'için, her biri için bir anlama cümlesi yerine bir yol belirleyebilmek *büyük bir fark yaratabilir. Ayrıca, JSONPath dile bağlı olmayan bir özelliktir ve hata ayıklama için çok kullanışlı olabilecek çevrimiçi test kullanıcıları bile vardır .


1

Sanırım aşağıdaki kadar basit aradığınızı verecek.

In[5]: ll = [{'value': 'apple', 'blah': 2}, {'value': 'banana', 'blah': 3} , {'value': 'cars', 'blah':4}]
In[6]: ld = [d.get('value', None) for d in ll]
In[7]: ld
Out[7]: ['apple', 'banana', 'cars']

Bunu mapve kombinasyonuyla da yapabilirsiniz, lambdaancak liste kavrayışı daha zarif ve pitonik görünür.

Daha küçük bir giriş listesi anlama için gitmek için bir yol ama giriş gerçekten büyükse, o zaman jeneratörler ideal bir yol sanırım.

In[11]: gd = (d.get('value', None) for d in ll)
In[12]: gd
Out[12]: <generator object <genexpr> at 0x7f5774568b10>
In[13]: '-'.join(gd)
Out[13]: 'apple-banana-cars'

Daha büyük girdi için olası tüm çözümlerin karşılaştırması

 In[2]: l = [{'value': 'apple', 'blah': 2}, {'value': 'banana', 'blah': 3} , {'value': 'cars', 'blah':4}] * 9000000
In[3]: def gen_version():
  ...:     for i in l:
  ...:         yield i.get('value', None)
  ...: 
In[4]: def list_comp_verison():
  ...:     return [i.get('value', None) for i in l]
  ...: 
In[5]: def list_verison():
  ...:     ll = []
  ...:     for i in l:
  ...:         ll.append(i.get('value', None))
  ...:     return ll
In[10]: def map_lambda_version():
   ...:      m = map(lambda i:i.get('value', None), l)
   ...:      return m
   ...: 
In[11]: %timeit gen_version()
172 ns ± 0.393 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In[12]: %timeit map_lambda_version()
203 ns ± 2.31 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In[13]: %timeit list_comp_verison()
1.61 s ± 20.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In[14]: %timeit list_verison()
2.29 s ± 4.58 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Gördüğünüz gibi, jeneratörler diğerlerine göre daha iyi bir çözümdür, harita da jeneratörle karşılaştırıldığında daha yavaştır, çünkü anlamak için OP'ye bırakacağım.


1

Örneği takip edin --

songs = [
{"title": "happy birthday", "playcount": 4},
{"title": "AC/DC", "playcount": 2},
{"title": "Billie Jean", "playcount": 6},
{"title": "Human Touch", "playcount": 3}
]

print("===========================")
print(f'Songs --> {songs} \n')
title = list(map(lambda x : x['title'], songs))
print(f'Print Title --> {title}')

playcount = list(map(lambda x : x['playcount'], songs))
print(f'Print Playcount --> {playcount}')
print (f'Print Sorted playcount --> {sorted(playcount)}')

# Aliter -
print(sorted(list(map(lambda x: x['playcount'],songs))))

1

Python'daki sözlükler listesinden anahtar değerler mi aldınız?

  1. Python'daki sözlükler listesinden anahtar değerler mi aldınız?

Ör:

data = 
[{'obj1':[{'cpu_percentage':'15%','ram':3,'memory_percentage':'66%'}]},
{'obj2': [{'cpu_percentage':'0','ram':4,'memory_percentage':'35%'}]}]

verilerdeki d için:

  for key,value in d.items(): 

      z ={key: {'cpu_percentage': d['cpu_percentage'],'memory_percentage': d['memory_percentage']} for d in value} 
      print(z)

Çıktı:

{'obj1': {'cpu_percentage': '15%', 'memory_percentage': '66%'}}
{'obj2': {'cpu_percentage': '0', 'memory_percentage': '35%'}}

-2

Bunu yapmanın çok basit bir yolu:

list1=['']
j=0
for i in com_list:
    if j==0:
        list1[0]=(i['value'])
    else:
        list1.append(i['value'])
    j+=1

Çıktı:

['elma', 'muz', 'arabalar']

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.