Getting a list of values from a list of dicts

前端 未结 9 624
执念已碎
执念已碎 2020-11-22 15:22

I have a list of dicts like this:

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


        
相关标签:
9条回答
  • 2020-11-22 15:24

    A very simple way to do it is:

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

    Output:

    ['apple', 'banana', 'cars']

    0 讨论(0)
  • 2020-11-22 15:27

    Here's another way to do it using map() and lambda functions:

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

    where l is the list. I see this way "sexiest", but I would do it using the list comprehension.

    Update: In case that 'value' might be missing as a key use:

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

    Update: I'm also not a big fan of lambdas, I prefer to name things... this is how I would do it with that in mind:

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

    I would even go further and create a sole function that explicitly says what I want to achieve:

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

    With Python 3, since map returns an iterator, use list to return a list, e.g. list(map(operator.itemgetter('value'), l)).

    0 讨论(0)
  • 2020-11-22 15:27

    Please try out this one.

    d =[{'value': 'apple', 'blah': 2},  {'value': 'banana', 'blah': 3} , {'value': 
    'cars', 'blah': 4}] 
    b=d[0]['value']
    c=d[1]['value']
    d=d[2]['value']
    new_list=[b,c,d]
    print(new_list)
    

    Output:

    ['apple', 'banana', 'cars']
    
    0 讨论(0)
  • 2020-11-22 15:31
    [x['value'] for x in list_of_dicts]
    
    0 讨论(0)
  • 2020-11-22 15:36

    I think as simple as below would give you what you are looking for.

    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']
    

    You can do this with a combination of map and lambda as well but list comprehension looks more elegant and pythonic.

    For a smaller input list comprehension is way to go but if the input is really big then i guess generators are the ideal way.

    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'
    

    Here is a comparison of all possible solutions for bigger input

     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)
    

    As you can see, generators are a better solution in comparison to the others, map is also slower compared to generator for reason I will leave up to OP to figure out.

    0 讨论(0)
  • 2020-11-22 15:39

    For a very simple case like this, a comprehension, as in Ismail Badawi's answer is definitely the way to go.

    But when things get more complicated, and you need to start writing multi-clause or nested comprehensions with complex expressions in them, it's worth looking into other alternatives. There are a few different (quasi-)standard ways to specify XPath-style searches on nested dict-and-list structures, such as JSONPath, DPath, and KVC. And there are nice libraries on PyPI for them.

    Here's an example with the library named dpath, showing how it can simplify something just a bit more complicated:

    >>> 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'}]}
    

    Or, using 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']
    

    This one may not look quite as simple at first glance, because find returns match objects, which include all kinds of things besides just the matched value, such as a path directly to each item. But for more complex expressions, being able to specify a path like '*.[*].value' instead of a comprehension clause for each * can make a big difference. Plus, JSONPath is a language-agnostic specification, and there are even online testers that can be very handy for debugging.

    0 讨论(0)
提交回复
热议问题