Сортировка итераций по предпочтительному порядку строк - PullRequest
2 голосов
/ 13 апреля 2011

Предположим, у меня есть список / кортеж, подобный этому:

MyLocation = 'DE'
(    
('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),
('Pencils', '', 19.95, 'PVT', 'IT'),
('Pencils', '', 23.50, 'PRF1', 'US'),
('Pencils', 'Wooden Pencils', 23.50, 'PRF2', 'DE'),
('Pencils', '', 12.50, 'NON', 'DE'))   

Я хочу отсортировать его в два прохода по следующим правилам:

1) Кортежи, соответствующие строке MyLocation 'DE' в элементе [4], сверху
Это промежуточный шаг, относительный порядок между DE s не имеет значения.Просто, чтобы все DE были наверху.

(    
('Pencils', '', 12.50, 'NON', 'DE'),
('Pencils', 'Wooden Pencils', 23.50, 'PRF2', 'DE'),
('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),    
('Pencils', '', 23.50, 'PRF1', 'US'),
('Pencils', '', 19.95, 'PVT', 'IT')       
)  

2) После этого сортируйте по элементу [3] rd, предпочтительный порядок должен быть ['PRF1', 'PRF2', 'PRF3'].Другие строки можно оставить в нижних позициях.

Мой ожидаемый окончательный отсортированный результат -

(    
('Pencils', '', 23.50, 'PRF1', 'US'),
('Pencils', 'Wooden Pencils', 23.50, 'PRF2', 'DE'),
('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),    
('Pencils', '', 12.50, 'NON', 'DE'),
('Pencils', '', 19.95, 'PVT', 'IT')       
)  

Как бы я поступил с этими двумя видами сортировки?Я могу управлять первой сортировкой с помощью del и insert, но каков рекомендуемый способ?

tempList = actualList
i = 0
for record in actualList:
    if record[5] == 'DE':
        del tempList[i]
        tempList.insert(0, record)
    i = i + 1
actualList = tempList

Меня особенно смущает, как мне поступить со второй сортировкой.Пожалуйста, предоставьте образцы кода для второй сортировки.

Ответы [ 4 ]

2 голосов
/ 12 апреля 2012

этого достаточно:

PRF = ('PRF1', 'PRF2', 'PRF3')
sorted(records, key=lambda x:(x[4]!='DE', PRF.index(x[3]) if x[3] in PRF else 3))

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

k = lambda x: (x[4]!='DE', PRF.index(x[3]) if x[3] in PRF else len(PRF))

, а затем просто использовать

sorted(records, key=k)

в вашем примере:

>>> records = ( ('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),
... ('Pencils', '', 19.95, 'PVT', 'IT'),
... ('Pencils', '', 23.50, 'PRF1', 'US'),
... ('Pencils', 'Wooden Pencils', 23.50, 'PRF2', 'DE'),
... ('Pencils', '', 12.50, 'NON', 'DE') )
>>> import pprint
>>> pprint.pprint(sorted(records, key=k))
[('Pencils', 'Wooden Pencils', 23.5, 'PRF2', 'DE'),
 ('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),
 ('Pencils', '', 12.5, 'NON', 'DE'),
 ('Pencils', '', 23.5, 'PRF1', 'US'),
 ('Pencils', '', 19.95, 'PVT', 'IT')]
1 голос
/ 13 апреля 2011

Вам нужен только один проход со специальной функцией ключа.

def key(t):
    return (
        dict(PRF1=0, PRF2=1, PRF3=2).get(t[3], 3), # earlier ones get smaller numbers
        int(t[4] != 'DE')) # 0 if DE, 1 otherwise

L.sort(key=key)

Функция ключа возвращает значение, которое будет использоваться для сравнения элементов в списке.Этот возвращает кортеж из двух элементов, и кортежи сравниваются на основе самого раннего элемента.Так что (1, 0) < (2, -300), потому что 1 <2. </p>

Первое значение - это индекс t[3] в списке ['PRF1', 'PRF2', 'PRF3'] или число 3, если это не так.Это означает, что чем раньше в списке он находится, тем ниже значение и тем раньше результаты сортировки.Второе значение уже объяснено в комментариях.:)

1 голос
/ 13 апреля 2011

Общая идея состоит в том, чтобы дать каждому пункту оценку. Если у вас есть несколько баллов за предмет, вы можете поместить его в кортеж.

MyLocation = 'DE'
location_score = { MyLocation : 1 }
that_other_field_score = {'PRF1' : 3, 'PRF2' : 2, 'PRF3' : 1}

def score( row ):
    # returns a tuple of item score
    # items not in the score dicts get score 0 for that field
    return ( that_other_field_score.get(row[3], 0),
                  location_score.get(row[4], 0))    

data = [    
('Pencils', 'Artists Pencils', 18.95, 'PVT', 'DE'),
('Pencils', '', 19.95, 'PVT', 'IT'),
('Pencils', '', 23.50, 'PRF1', 'US'),
('Pencils', 'Wooden Pencils', 23.50, 'PRF2', 'DE'),
('Pencils', '', 12.50, 'NON', 'DE')]

# sort data, highest score first
data.sort(key=score, reverse=True)
print data 

Дикт location_score, возможно, немного излишним (вы могли бы просто написать (1 if row[4]=='DE' else 0)), но, с другой стороны, его можно легко расширить таким образом.

0 голосов
/ 13 апреля 2011

Это немного глупо, но так и должно быть.

def prf_key(item):
    if item[3][:3] == 'PRF':
        return (0, int(item[3:]))
    else:
        return (1, None)

actualList.sort(key = prf_key)

Идея состоит в том, что любой PRF должен идти сверху, поэтому он возвращает кортеж, начинающийся с 0, остальные с 1; затем PRF сортируются между собой по количеству.

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