简体   繁体   中英

Sorting a list of python dictionaries based on keys in dictionaries (where some list items are missing those keys )

I am trying to sort a list of python dictionaries based on some keys in dictionary object, where some of list items are missing those keys and i don't want those items in sorted list.

list = [{'fieldname': 'acc', 'fieldtype': 'Label'},
        {'person': 'sid', 'from_month':7, 'from_year': 2019},
        {'person': 'Jane', 'from_month':7, 'from_year': 2019},
        {'person': 'sky', 'from_month':12, 'from_year': 2018},
        {'person': 'james', 'from_month':1, 'from_year': 2020}]

list = sorted(columns, key = lambda i: (i['from_month'], i['from_year'], i['person']))

Is there pythonic way to check if a specific key-value pair exist in list and only then sort and remove other items.

You could try the following, in order to check if key exists in the dict:

list = sorted(columns, key = lambda i: tuple(i[k] for k in ['from_month', 'from_year', 'person'] if k in i))
In [308]: L = [{'fieldname': 'acc', 'fieldtype': 'Label'}, 
     ...:         {'person': 'sid', 'from_month':7, 'from_year': 2019}, 
     ...:         {'person': 'Jane', 'from_month':7, 'from_year': 2019}, 
     ...:         {'person': 'sky', 'from_month':12, 'from_year': 2018}, 
     ...:         {'person': 'james', 'from_month':1, 'from_year': 2020}]                                                                                                                                                                                                       

In [309]: my_key = 'from_month'                                                                                                                                                                                                                                                 

In [310]: my_val = 7                                                                                                                                                                                                                                                            

In [311]: sorted([d for d in L if d.get(my_key, None)==my_val], key=operator.itemgetter(my_key))                                                                                                                                                                                
Out[311]: 
[{'person': 'sid', 'from_month': 7, 'from_year': 2019},
 {'person': 'Jane', 'from_month': 7, 'from_year': 2019}]

How do you sort a list with some items removed? You remove them. Then you sort.

# function to determine if entry should be included or not
def include(entry):
    required = ['person', 'from_year', 'from_month']
    for term in required:
        if term not in entry:
            return False
    return True

# function for sorting entries
key_function = lambda entry: (entry['from_year'], entry['from_month'], entry['person'])

all_data = [
    {'fieldname': 'acc', 'fieldtype': 'Label'},
    {'person': 'sid', 'from_month':7, 'from_year': 2019},
    {'person': 'Jane', 'from_month':7, 'from_year': 2019},
    {'person': 'sky', 'from_month':12, 'from_year': 2018},
    {'person': 'james', 'from_month':1, 'from_year': 2020}
]

# filter out unwanted items (either method)
reduced_list1 = [entry for entry in all_data if include(entry)]
reduced_list2 = filter(include, all_data)

# sort (list.sort or sorted)
sorted_reduced_list = sorted(reduced_list2, key=key_function)

for entry in sorted_reduced_list:
    print(entry)

If you want to create a reduced list, use a list comprehension with an if clause. This creates the reduced list without changing the original. You then sort it normally.

reduced_list1 = [entry for entry in all_data if include(entry)]

However, if you are doing something that can benefit from an iterator, then you should use filter ( https://docs.python.org/3/library/functions.html#filter ) Unfortunately, you'll need the full result before you can sort it, so the iterator doesn't help here.

A caution - I see you defined a variable named "list" in your original question. Don't do that. That shadows the name of the list class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM