2015-08-09 2 views
0

сортировки У меня есть некоторые данные в формате JSON, я прочитал из файла с помощью json.load(data_file)Сортировка словарь с пользовательской функцией

{ 
    "unused_account":{ 
    "logins": 0, 
    "date_added": 150 
    }, 
    "unused_account2":{ 
    "logins": 0, 
    "date_added": 100 
    }, 
    "power_user_2": { 
    "logins": 500, 
    "date_added": 400, 
    "date_used": 500 
    }, 
    "power_user": { 
    "logins": 500, 
    "date_added": 300, 
    "date_used": 400 
    }, 
    "regular_user": { 
    "logins": 20, 
    "date_added": 200, 
    "date_used": 300 
    } 
} 

Я хочу, чтобы отсортировать записи в определенном порядке. Я нашел множество примеров для сортировки по ключевым или одному значению. Но я хотел бы отсортировать значения по этим правилам:

  1. GroupBy логинов нисходящих, но пользователи с 0 логинов первых
  2. пользователей сортировки с 0 логинов по DATE_ADDED пользователей сортировки
  3. , по крайней мере, 1 вход по date_used

В идеале я хотел бы написать мой собственный функцию сравнения, как это:

def compare(elem1, elem2): 
    """Return >0 if elem2 is greater than elem1 
     <0 if elem2 is lesser than elem1 
     0 if they are equal""" 
    #rule 1 group by logins 
    if elem1['logins'] != elem2['logins']: 
     if elem1['logins'] == 0: 
      return -1 
     if elem2['logins'] == 0: 
      return 1 
     return elem2['logins'] - elem1['logins'] 
    # rule 2 sort on date_added 
    if elem1['logins'] == 0 and elem2['logins'] == 0: 
     return elem2['date_added'] - elem1['date_added'] 
    #rule 3 sort on date_used 
    if elem1['logins'] == elem2['logins'] and elem1['loigns'] > 0: 
     return elem2['date_used'] - elem1['date_used'] 
    return 0 # default 

Я не KNO w где и как подключить мою функцию сортировки.

+0

Можете ли вы дать нам ожидаемый результат своего рода? так что вам нужно сначала ввести 0 логинов (отсортировано по дате, добавленному в каком направлении? Тогда остальное с использованием логинов по дате, опять же, в каком направлении? –

+0

Ах, нет, вы хотите сначала войти в систему, затем войти в систему и * в группе с такое же количество логинов *, это сортировка даты, по убыванию. –

+2

Словари - это неупорядоченные типы данных, вы можете посмотреть [OrderedDict] (https://docs.python.org/2/library/collections.html# collection.OrderedDict) из модуля коллекций. –

ответ

1

Я предполагаю, что вы знаете, что словари неупорядочены и что вы хотите сортировать значения или пары ключ-значение. Следующие примеры сортируют значения.

Ваша функция сравнения уже работает, если вы исправить loigns опечатку в последнем if:

>>> sorted(sample.itervalues(), cmp=compare)) 
[{'logins': 0, 'date_added': 150}, {'logins': 0, 'date_added': 100}, {'logins': 500, 'date_added': 400, 'date_used': 500}, {'logins': 500, 'date_added': 300, 'date_used': 400}, {'logins': 20, 'date_added': 200, 'date_used': 300}] 
>>> pprint(_) 
[{'date_added': 150, 'logins': 0}, 
{'date_added': 100, 'logins': 0}, 
{'date_added': 400, 'date_used': 500, 'logins': 500}, 
{'date_added': 300, 'date_used': 400, 'logins': 500}, 
{'date_added': 200, 'date_used': 300, 'logins': 20}] 

Однако, вы можете использовать следующий ключ сортировки тоже:

(not d['logins'], d['logins'], d['date_used'] if d['logins'] else d['date_added']) 

Это создает кортеж от (has_logins, num_logins, date), где выбранная дата основана на том, был ли пользователь вошел в систему.

Использовать i т как key аргумента функции sorted() и обратного рода, например:

>>> key = lambda d: (not d['logins'], d['logins'], d['date_used'] if d['logins'] else d['date_added']) 
>>> pprint(sorted(sample.itervalues(), key=key, reverse=True)) 
[{'date_added': 150, 'logins': 0}, 
{'date_added': 100, 'logins': 0}, 
{'date_added': 400, 'date_used': 500, 'logins': 500}, 
{'date_added': 300, 'date_used': 400, 'logins': 500}, 
{'date_added': 200, 'date_used': 300, 'logins': 20}] 

Если нужны ключи, а также, использовать dict.iteritems() и обновить функциональную клавишу, чтобы принять (k, d) кортеж:

>>> key = lambda (k, d): (not d['logins'], d['logins'], d['date_used'] if d['logins'] else d['date_added']) 
>>> pprint(sorted(sample.iteritems(), key=key, reverse=True)) 
[('unused_account', {'date_added': 150, 'logins': 0}), 
('unused_account2', {'date_added': 100, 'logins': 0}), 
('power_user_2', {'date_added': 400, 'date_used': 500, 'logins': 500}), 
('power_user', {'date_added': 300, 'date_used': 400, 'logins': 500}), 
('regular_user', {'date_added': 200, 'date_used': 300, 'logins': 20})] 
+0

Спасибо, я ведь тоже нуждался в ключах. Спасибо, что включили этот фрагмент. – Diemex

Смежные вопросы