Python словарь для сортировки кортежей, это может быть сделано лучше?

1

У меня есть диктор для моего ввода со следующими характеристиками:

  • Каждое значение будет либо целым, либо строковым, либо итерируемым (кроме строки).
  • Если элемент является итерируемым, каждый элемент в этом итерабеле будет только строкой или целым числом.

например:

mydict = {
    'one': 1,
    'two': '23',
    'three': 3,
    'four': [
        7,
        '6',
        5,
        8
    ],
    'nine': 9
}

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

('four', 5)
('four', 7)
('four', 8)
('four', '6')
('nine', 9)
('one', 1)
('three', 3)
('two', '2')

В настоящее время это реализовано с использованием следующего генератора:

def dict_to_sorted_tuples(unsorted_dict):
    for key in sorted(unsorted_dict):
        if isinstance(unsorted_dict[key], basestring):
            yield key, unsorted_dict[key]
            continue
        try:
            for v in sorted(unsorted_dict[key]):
                yield key, v
        except:
            yield key, unsorted_dict[key]

print list(dict_to_sorted_tuples(mydict))

Я чувствую, что это можно сделать чище, любые предложения по улучшению?

Теги:
sorting
dictionary
generator
iterable

3 ответа

5
Лучший ответ
>>> sorted((i,k) for i,j in mydict.items() for k in ([j] if isinstance(j, str) or isinstance(j, int) else j))
[('four', 5), ('four', 7), ('four', 8), ('four', '6'), ('nine', 9), ('one', 1), ('three', 3), ('two', '2')]

Идея здесь в том, что если значение является int или str, вы помещаете его в list. Теперь проблема упрощена, потому что у вас есть значение, которое вы всегда можете перебрать

Если вы действительно уверены, что вам нужно только проверить int или str (не подклассы или юникод), вы можете просто использовать

sorted((i,k) for i,j in mydict.items() for k in ([j] if type(j) in (int, str) else j))

Если значение может быть unicode, вы должны использовать isinstance(j, basestring) вместо isinstance(j, str)

  • 0
    Вы уверены, что знаете, как превратить что-то в одну строку! :) +1
  • 1
    @Trufa В этом случае я бы предложил не делать это в одной строке. По крайней мере, если оставить это как есть, это должно вызвать многострочный комментарий, объясняющий, что он делает для тех, кто должен прийти и поддержать его. Умный и выразительный, но требует объяснения.
1
for values in sorted(mydict.items()):
    if isinstance(values[1], list):
        for x in sorted(values[1]):
            print (values[0], x,)
    else:
        print values
  • 1
    легко читаемый
  • 0
    Значит, нет других элементов, кроме списков? Кроме того, я бы обнаружил, for key, value in sorted(mydict.items()) гораздо более читабельны, так как вам не нужно использовать values[0] и values[1] .
Показать ещё 1 комментарий
0
def dict_to_sorted_tuples(unsorted_dict):
    res = []
    for k, v in sorted(unsorted_dict.iteritems()):
        if isinstance(v, (list, tuple)):
            res.extend((k, _v) for _v in sorted(v))
        else:
            res.append((k, v))
    return res

Ещё вопросы

Сообщество Overcoder
Наверх
Меню