Как я могу отсортировать сложный словарь ключ - PullRequest
1 голос
/ 14 октября 2011

У меня есть эти действительно сложные файлы данных, которые я обработал, и, когда обрабатывается каждый файл, я использовал OrdDictionary для захвата ключей и значений.Каждый заказанный словарь добавляется в список, поэтому мой окончательный результат - список словарей.Из-за разнообразия данных, захваченных в этих файлах, у них много общих ключей, но достаточно необычных ключей, чтобы сделать экспорт данных в Excel более сложным, чем я надеялся, потому что мне действительно нужно выталкивать данные в согласованном виде.структура.

Каждый ключ имеет структуру, подобную

Q_#_SUB_A_COLUMN_#_NUMB_#

, поэтому, например, у меня есть

 Q_123_SUB_D_COLUMN_C_NUMB_17

Мы можем перевести ключ следующим образом

 Question 123
 SubItem D
 Column C
 Instance 17

Поскольку существует подэлемент D, столбец C и экземпляр 17, должны быть SubItemA, столбец B и экземпляр 16

Однако один из исходных файлов может быть заполнен значениями данных (и ключами, которые находятся в диапазонедо приведенного выше примера, и некоторые другие исходные файлы могут заканчиваться

Q_123_SUB_D_COLUMN_C_NUMB_13

, поэтому, когда я перебираю список словарей, чтобы извлечь все экземпляры уникальных ключей, чтобы я мог использовать их в csv.dictwriter в качествезаголовки столбцов мой план состоял в том, чтобы отсортировать итоговый список уникальных заголовков столбцов, но я не могу заставить сортировку работать

speособенно мне нужно отсортировать так, чтобы результаты выглядели так:

 Q_122_SUB_A_COLUMN_C_NUMB_1
 Q_122_SUB_B_COLUMN_C_NUMB_1
 Q_123_SUB_A_COLUMN_C_NUMB_1
 Q_123_SUB_B_COLUMN_C_NUMB_1
 Q_123_SUB_C_COLUMN_C_NUMB_1
 Q_123_SUB_D_COLUMN_C_NUMB_1
 dot
 dot
 dot
 Q_123_SUB_A_COLUMN_C_NUMB_17
 Q_123_SUB_B_COLUMN_C_NUMB_17
 Q_123_SUB_C_COLUMN_C_NUMB_17
 Q_123_SUB_D_COLUMN_C_NUMB_17

Большая проблема в том, что я не знаю, прежде чем открывать какой-либо конкретный набор этих файлов, сколько ответов дано, сколько подвопросовответы, сколько столбцов связано с каждым вопросом или подвопросом или сколько существует экземпляров какой-либо конкретной комбинации вопросов, подвопросов или столбцов, и я не хочу.Используя Python, я смог сократить более 1200 строк кода SAS до 95, но это последний маленький момент, прежде чем я начну записывать его в файл CSV, который я не могу понять.

Любые замечания приветствуются.

Мой план состоит в том, чтобы найти все уникальные ключи, просматривая список словарей, а затем правильно отсортировать эти ключи, чтобы я мог затем создать файл csv, используя ключи в качестве заголовков столбцов.Я знаю, что могу найти уникальные ключи, вытолкнуть их, вручную отсортировать, а затем прочитать отсортированный файл обратно, но это кажется неуклюжим.

Ответы [ 3 ]

4 голосов
/ 14 октября 2011

Просто укажите достаточно умную функцию в качестве ключа при сортировке.

>>> (lambda x: tuple(y(z) for (y, z) 
                     in zip((int, str, str, int), 
                            x.split('_')[1::2])))('Q_122_SUB_A_COLUMN_C_NUMB_1')
(122, 'A', 'C', 1)
2 голосов
/ 14 октября 2011

Вы можете использовать регулярное выражение для извлечения различных частей ключа и использовать их для сортировки.

Например,

import re

names = '''Q_122_SUB_A_COLUMN_C_NUMB_1
Q_122_SUB_B_COLUMN_C_NUMB_1
Q_123_SUB_B_COLUMN_C_NUMB_1
Q_123_SUB_A_COLUMN_C_NUMB_17
Q_123_SUB_D_COLUMN_C_NUMB_1
Q_123_SUB_B_COLUMN_C_NUMB_17
Q_123_SUB_C_COLUMN_C_NUMB_1
Q_123_SUB_C_COLUMN_C_NUMB_17
Q_123_SUB_A_COLUMN_C_NUMB_1
Q_123_SUB_D_COLUMN_C_NUMB_17'''.split()

def key(name, match=re.compile(r'Q_(\d+)_SUB_(\w+)_COLUMN_(\w+)_NUMB_(\d+)').match):
    # not sure what the actual order is, adjust the priorities accordingly
    return tuple(f(value) for f, value in zip((str, int, int, str), match(name).group(3, 4, 1, 2)))

for name in names:
    print name

names.sort(key=key)

print

for name in names:
    print name

Чтобы объяснить извлечение ключаПроцесс, мы знаем, что ключи имеют определенный шаблон.Регулярное выражение прекрасно работает здесь.

r'Q_(\d+)_SUB_(\w+)_COLUMN_(\w+)_NUMB_(\d+)'
#     ^         ^            ^          ^
#     digits    letters      letters    digits
#     group 1   group 2      group 3    group 4

В регулярных выражениях части строки, заключенные в скобки, являются группами.\d представляет любую десятичную цифру.+ означает, что должен быть один или несколько предыдущих символов.Так \d+ означает одну или несколько десятичных цифр.\w соответствует букве.

Если строка соответствует этому шаблону, мы могли бы получить легкий доступ к каждой группировке в этой строке, используя метод group.Вы можете получить доступ к нескольким группам, просто добавив больше номеров групп

например,

m = match('Q_122_SUB_B_COLUMN_C_NUMB_1')
# m.group(1) == '122'
# m.group(2) == 'B'
# m.group(3, 4) == ('C', '1')

Это похоже на подход Игнасио, только намного более строгий по шаблону.Как только вы сможете обернуть голову вокруг этого, создание соответствующего ключа для сортировки должно быть простым.

0 голосов
/ 14 октября 2011

Предполагая, что ключи содержатся в списке, скажем, keyList

list_to_sort=[]

for key in keyList:
    sortKeys=key.split('_')
    keyTuple=(sortKeys[1],sortKeys[-1],sortKeys[3],sortKeys[5],key)
    list_to_sort.append(keyTuple)

после этого элементы в списке - это кортежи, которые выглядят как

 (123,17,D,C,Q_123_SUB_D_COLUMN_C_NUMB_17)


from operator import itemgetter

list_to_sort.sort(key=itemgetter(0,1,2,3)

Я не уверен точно, что делает itemgetter, но это работает и кажется более простым, но менее элегантным, чем два других решения.

Обратите внимание, что я расположил ключи в кортеже так, чтобы они сортировались в порядке, отличающемся от способа отображения ключей в реальном времени. Это не было необходимым, я мог бы сделать

for key in keyList:
    sortKeys=key.split('_')
    keyTuple=(sortKeys[1],sortKeys[3],sortKeys[5],sortKeys[7],key)
    list_to_sort.append(keyTuple)

, а затем сделал сортировку, как это

list_to_sort.sort(key=itemgetter(0,3,1,2)

Мне было легче отследить первый до

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...