2011-10-14 2 views
1

У меня есть эти очень сложные файлы данных, которые я обработал, и по мере обработки каждого файла я использовал упорядоченный документ для захвата ключей и значений. Каждый упорядоченныйDictionary добавляется в список, поэтому мой конечный результат - список словарей. Из-за разнообразия данных, записанных в этих файлах, у них много общих ключей, но есть достаточно необычных ключей, чтобы сделать экспорт данных в 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, поскольку заголовки столбцов моего плана состояли в сортировке результирующего списка уникальных заголовков столбцов, но я не могу заставить сортировать работу

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

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 с помощью клавиш в виде заголовков столбцов. Я знаю, что я могу найти уникальные клавиши, которые выталкивают это и сортируют вручную, а затем читают отсортированный файл, но это кажется неуклюжим.

ответ

4

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

>>> (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) 
+0

Так как я могу научиться переводить этот впечатляющий бит кода – PyNEwbie

+0

Начните с нарезки, затем пройдите свой путь к лямбда. –

+0

Я нахожусь на нем спасибо – PyNEwbie

2

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

например,

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 

В регулярных выражениях части строки, обернутые в parens, являются группами. \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

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

+0

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

+0

Вау, это было очень мило с твоей стороны, чтобы прояснить это, я ценю твою проблему. – PyNEwbie

0

Предполагая, что ключи содержатся в списке, скажем 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) 

Это было легче для меня, чтобы отслеживать первый через

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