2010-09-02 3 views
8

Обс: Я знаю, что списки в python не исправлены по порядку, но думаю, что это будет. И я использую Python 2.4Python: Как заказать заказ?

У меня есть список, как (например) этот:

mylist = [ (u'Article', {"...some_data..."} ) , 
      (u'Report' , {"...some_data..."} ) , 
      (u'Book' , {"...another_data..."}) , 
...#continue 
] 

Эта переменная MyList получается из функции, а «порядок» в списке вернулся будет отличаться. Поэтому иногда это будет похоже на пример. Иногда «Отчет» приходит до «Статьи» и т. Д.

У меня есть фиксированный заказ, который я хочу в этом списке (и не в алфавитном порядке).

Допустим, что мой фиксированный порядок: «Доклад», «Статья», «Книга», ...

Итак, что я хочу, что: независимо от того, «MyList» конкретизируется, я хочу переделать его, чтобы «Отчет» оставался на фронте, «Article» на второй и т. д.

Какой лучший подход к изменению порядка моего списка (взяв первый элемент кортежа каждого элемента в списке), используя мой «пользовательский» ' заказ?

Ответ:

Я закончил с этим:

MyList стал список dicts, как это:

mylist = [{'id':'Article', "...some_data..."} , 
     ...etc 
] 

каждый ДИКТ имеющий 'идентификатор', который должен был сортироваться.

Сохранение правильного порядка на listAssigning в correct_order на списке:

correct_order = ['Report', 'Article', 'Book', ...] 

и делает:

results = sorted([item for item in results], cmp=lambda x,y:cmp(correct_order.index(x['id']), correct_order.index(y['id']))) 

ответ

13

Вы можете использовать словарь, который будет сопоставлять каждый первый элемент с его «весом», а затем проверять этот словарь внутри функции сортировки.

Что-то вроде:

d = { "Report": 1, 
     "Article": 2, 
     "Book": 3 } 
result = sorted(mylist, key=lambda x:d[x[0]]) 
+10

Лучше использовать ключевую функцию, а не устаревшую функцию cmp, которая больше не выходит из Python 3: 'sorted (mylist, key = lambda x: d [x [0]]) –

+0

Не пытался еще Python 3, так что Я не знал .. Спасибо :) – Joril

+2

Это также рекомендуется для Python 2, поскольку использование ключевой функции выполняется быстрее, чем функция cmp. См. Http://docs.python.org/library/functions.html#sorted –

6

Вы можете использовать словарь, который позволит вам получить доступ к "Book", «Статья» и т. Д., Не заботясь о порядке. Я хотел бы поместить данные из этого списка в Словарь, которые выглядят так:

mydict = { u'Article': "somedata", 
      u'Report': "someotherdata", ...} 

Если вы действительно хотите, чтобы отсортировать список так, как вы описали, вы можете использовать list.sort с ключевой функцией, которая представляет ваши конкретную порядок сортировки (Documentation). Вам нужна ключевая функция, так как вам нужен только первый элемент, и ваш порядок сортировки также не является алфавитным.

+2

http://wiki.python.org/moin/HowTo/Sorting/ снова, эта связь является наиболее полезно в этом вопросе! – dmitko

0

Этот способ создает Dict и тянет элементы из него в порядке

mylist = [ (u'Article', {"...some_data..."} ) , 
      (u'Report' , {"...some_data..."} ) , 
      (u'Book' , {"...another_data..."}) , 
] 

mydict = dict(mylist) 
ordering = [u'Report', u'Article', u'Book'] 

print [(k,mydict[k]) for k in ordering] 

Этот способ использует сорт с O (1) Lookups для упорядочения

mylist = [ (u'Article', {"...some_data..."} ) , 
      (u'Report' , {"...some_data..."} ) , 
      (u'Book' , {"...another_data..."}) , 
] 

mydict = dict(mylist) 
ordering = dict((k,v) for v,k in enumerate([u'Report', u'Article', u'Book'])) 

print sorted(mydict.items(), key=lambda (k,v): ordering[k]) 
1

В целом, могут быть элементы mylist, которые не указаны в указанном фиксированном порядке. Это заказ в соответствии с правилом, но оставить в покое относительный порядок всего за пределами правила:

def orderListByRule(alist,orderRule,listKeys=None,dropIfKey=None): 
    ### 
    ####################################################################################### 
    """ Reorder alist according to the order specified in orderRule. The orderRule lists the order to be imposed on a set of keys. The keys are alist, if listkeys==None, or listkeys otherwise. That is, the length of listkeys must be the same as of alist. That is, listkeys are the tags on alist which determine the ordering. orderRule is a list of those same keys and maybe more which specifies the desired ordering. 
    There is an optional dropIfKey which lists keys of items that should be dropped outright. 
    """ 
    maxOR = len(orderRule) 
    orDict = dict(zip(orderRule, range(maxOR))) 
    alDict = dict(zip(range(maxOR, maxOR+len(alist)), 
         zip(alist if listKeys is None else listKeys, alist))) 
    outpairs = sorted( [[orDict.get(b[0],a),(b)] for a,b in alDict.items()] ) 
    if dropIfKey is None: dropIfKey=[] 
    outL = [b[1] for a,b in outpairs if b[0] not in dropIfKey] 
    return outL 

def test_orderListByRule(): 
    L1 = [1,2,3,3,5] 
    L2 = [3,4,5,10] 
    assert orderListByRule(L1, L2) == [3, 3, 5, 1, 2] 
    assert orderListByRule(L1, L2, dropIfKey=[2,3]) == [5, 1,] 
    Lv = [c for c in 'abcce'] 
    assert orderListByRule(Lv, L2, listKeys=L1) == ['c', 'c', 'e', 'a', 'b'] 
    assert orderListByRule(Lv, L2, listKeys=L1, dropIfKey=[2,3]) == ['e','a'] 
Смежные вопросы