Dedupe и сортировка списка в Python 2.2
В Python 2.2 (не спрашивайте), каков самый аккуратный способ сортировки списка и удаления дубликатов?
Я, очевидно, могу написать функцию, которая будет sort()
затем повторите, но мне интересно, есть ли идиоматический однострочный.
edit: список короткий, поэтому эффективность не является проблемой. Кроме того, элементы неизменны.
4 ответов
для старых версий python, и поскольку вы используете строки, я не могу придумать ни одного лайнера, но шаблон, вероятно, будет таким, используя словари:
def sorted_uniq(your_list):
table = {}
for s in your_list:
table[s] = None
k = table.keys()
k.sort()
return k
адаптировано из древнего фрагмента кода ActiveState, который сам Алекс Мартелли написал несколько комментариев:http://code.activestate.com/recipes/52560/
более короткий путь со списком постижений:
def sort_uniq(alist):
d = {}
mod_list = [d.setdefault(i,i) for i in alist if i not in d]
mod_list.sort()
return mod_list
помимо аккуратного Стивена (но немного непривлекательным) один вкладыш, я думаю, что это главное направление в наименьшее количество строк и самое идиоматические способ сделать это с Python 2.2:
благодаря Стивену Румбальски в комментариях, 2-я версия может быть сжата дальше с python в :
def sort_uniq(alist):
mod_list = dict(zip(alist,alist)).keys()
mod_list.sort()
return mod_list
если list.sort()
не работал побочным эффектом, у нас был бы один лайнер. ;)
идиоматическое и один вкладыш? Нет.
вот неидиоматический приклад-уродливый однострочный.
>>> x = [4, 3, 3, 2, 4, 1]
>>> [y for y in (locals().__setitem__('d',{}) or x.sort() or x)
if y not in d and (d.__setitem__(y, None) or True)]
[1, 2, 3, 4]
если простой двухслойный приемлемо:
x = [4, 3, 3, 2, 4, 1]
x = dict(map(None,x,[])).keys()
x.sort()
или сделайте две небольшие вспомогательные функции (работает для любой последовательности):
def unique(it):
return dict(map(None,it,[])).keys()
def sorted(it):
alist = [item for item in it]
alist.sort()
return alist
print sorted(unique([4, 3, 3, 2, 4, 1]))
дает
[1, 2, 3, 4]
и, наконец, полупитонный лайнер:
x = [4, 3, 3, 2, 4, 1]
x.sort() or [s for s, t in zip(x, x[1:] + [None]) if s != t]
для записи, Python 2.2 тут есть наборы, но под модулем" наборы", поэтому это поможет вам пройти долгий путь:
from sets import Set
myList = list(Set(myList))
# now we're duplicate-free, a standard sorting might be enough
myList.sort()
вероятно, лучший ответ-использовать двоичное дерево:
# Make yield work in Python 2.2
from __future__ import generators
class TreeNode(object):
def __init__(self, value):
self.left = None
self.right = None
self.value = value
def add(self, value):
if value == self.value:
return
if value < self.value:
if self.left is None:
self.left = TreeNode(value)
else:
self.left.add(value)
else:
if self.right is None:
self.right = TreeNode(value)
else:
self.right.add(value)
def __iter__(self):
if self.left is not None:
for value in self.left:
yield value
yield self.value
if self.right is not None:
for value in self.right:
yield value
class DedupeSorter(object):
def __init__(self):
self.root = None
def add(self, value):
if self.root is None:
self.root = TreeNode(value)
else:
self.root.add(value)
def __iter__(self):
if self.root is None:
return []
else:
return self.root.__iter__()
def dedupe_and_sort(l):
sorter = DedupeSorter()
for value in l:
sorter.add(value)
return list(sorter)
определенно не идиоматический, но должен быть быстрым. Он в основном создает набор на основе дерева и повторяет его. У меня нет Python 2.2, поэтому, надеюсь, он работает :p