2016-05-12 2 views
1

У меня есть два списка:сортировки списка карт

card_candidates = ['9D', '9S', '3S', '0D'] 
card_order = ['2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A'] 

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

sorted_candidates = ['3S', '9D', '9S', '0D'] 

«0» только значение 10, просто хотел, чтобы все карты той же длину. Если есть связь, как с «9D» и «9S», тогда буквы нужно будет отсортировать вместо этого. До сих пор я только что сделал это:

sorted_candidates = [] 
for x, y in zip(card_candidates, card_order): 
    sorted_candidates.append([x[0] for x in card_candidates]) 
return sorted(sorted_candidates) 

Я знаю, что это даже не близко к правой, я просто не знаю, как это сделать.

ответ

10

Производит словарь, отображающий ваши символы порядка сортировки в ряд, мы разберемся теми:

sort_map = {c: i for i, c in enumerate(card_order)} 

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

sorted_candidates = sorted(card_candidates, 
          key=lambda card: (sort_map[card[0]], card[1])) 

ключ сортировки принимает первый символ каждой карты и переводит, что целое число от sort_map словаря, который затем информирует sorted() функцию правильного порядка сортировки. В случае галстука (равная стоимость карты) карты сортируются в клубах, бриллиантах, сердцах, порядке пиков (при условии, что вы используете C и H для клубов и сердец).

Создание фронта отображения сохраняет сортировку в пределах сложности O (NlogN); вы можете сделать то же самое с card_order.index(card[0]), но затем вы вызываете list.index() звонок для каждого отсортированного элемента и list.index необходимо отсканировать список, создавая сортировку O (KNlogN) (где K - длина списка card_order).

Дем:

>>> card_candidates = ['9D', '9S', '3S', '0D'] 
>>> card_order = ['2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A'] 
>>> sort_map = {c: i for i, c in enumerate(card_order)} 
>>> sorted(card_candidates, key=lambda card: (sort_map[card[0]], card[1])) 
['3S', '9D', '9S', '0D'] 
>>> sorted(['9D', '9S', '9C', '9H'], key=lambda card: (sort_map[card[0]], card[1])) 
['9C', '9D', '9H', '9S'] 
+0

Спасибо за этот ответ. Удивительно, как хорошие люди на питоне на этом сайте. – RoadRunner

2

Вам не обязательно нужны какие-либо дополнительные структуры данных, то card_order список достаточно полностью, чтобы отсортировать карты с помощью этого простого Однострочника:

card_candidates = ['9D', '9S', '3S', '0D'] 
card_order = ['2', '3', '4', '5', '6', '7', '8', '9', '0', 'J', 'Q', 'K', 'A'] 

sorted_cards = sorted(card_candidates, key=lambda c: (card_order.index(c[0]), c[1])) 

print(list(sorted_cards)) 

Выхода:

['3S', '9D', '9S', '0D'] 

See this code running on ideone.com

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

+0

Абсолютно блестящий, спасибо @Byte Commander. – RoadRunner

+2

Созданное сопоставление позволяет избежать полного сканирования через 'card_order', который делает' list.index'. –

+1

@MartijnPieters Да, я должен согласиться.Если вам нужно сортировать много карточек и часто их сортировать, более эффективно использовать ваш подход, так как поиск хеша в словаре быстрее, чем сканирование списка для элемента с помощью 'index'. Но если это произойдет только один раз в начале игры, что не будет критическим по времени вариантом использования, эти несколько миллисекунд не должны иметь никакого значения. –

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