86

Given a list of strings, I want to sort it alphabetically and remove duplicates. I know I can do this:

from sets import Set
[...]
myHash = Set(myList)

but I don't know how to retrieve the list members from the hash in alphabetical order.

I'm not married to the hash, so any way to accomplish this will work. Also, performance is not an issue, so I'd prefer a solution that is expressed in code clearly to a fast but more opaque one.

Vladimir Panteleev
25.2k6 gold badges79 silver badges123 bronze badges
asked Jan 26, 2009 at 14:09
3
  • Also see here for more information Commented Mar 14, 2014 at 17:37
  • 1
    This question, after @ColonelPanic's edit, is kind of a mess; the question in the title and the question in the body are not the same. The title indicates that the original order, pre-duplicate-removal, should be preserved. But the body presents a scenario where this is not in fact necessary. Commented Sep 29, 2019 at 14:05
  • I changed the title to match the body and the accepted answer. Commented May 3, 2022 at 7:55

6 Answers 6

213

A list can be sorted and deduplicated using built-in functions:

myList = sorted(set(myList))
  • set is a built-in function for Python>= 2.3
  • sorted is a built-in function for Python>= 2.4
Bengt
14.5k7 gold badges53 silver badges67 bronze badges
answered Jan 26, 2009 at 14:16
8
  • 19
    This does not work if your myList has unhashable objects. Commented Nov 14, 2012 at 11:30
  • wouldn't set(sorted(myList)) be faster? I mean isn't it faster to first sort a list and then remove its duplicates than first removing its duplicates and only sort it afterwards? Commented Jan 26, 2017 at 19:27
  • 1
    @CorneliuZuzu Removing duplicates with set() changes order, so you have to do it this way Commented Jun 13, 2017 at 9:25
  • 2
    Downvoted because there is a distinction between ordered and sorted. Ordered means keep the original order, e.g. f([3,1,4,1,5,9,2,6,5,3,5]) = [3,1,4,5,9,2,6] Commented Dec 19, 2019 at 3:38
  • 1
    @user3667349 The "keep order" clause was not a part of the original question, it was added by the Colonel Panic edit in 2015. Commented Dec 24, 2019 at 17:18
14

If your input is already sorted, then there may be a simpler way to do it:

from operator import itemgetter
from itertools import groupby
unique_list = list(map(itemgetter(0), groupby(yourList)))
answered Jan 26, 2009 at 14:48
3
  • 5
    This can also be expressed as [e for e, _ in groupby(sortedList)] Commented Jan 26, 2009 at 15:25
  • This is O(n) rather than O(n log n) right? Commented Oct 19, 2015 at 14:55
  • FWIW something similar was added to the list of recipes from the documentation for itertools. Commented Feb 16, 2016 at 10:58
6

If you want to keep order of the original list, just use OrderedDict with None as values.

In Python2:

from collections import OrderedDict
from itertools import izip, repeat
unique_list = list(OrderedDict(izip(my_list, repeat(None))))

In Python3 it's even simpler:

from collections import OrderedDict
from itertools import repeat
unique_list = list(OrderedDict(zip(my_list, repeat(None))))

If you don't like iterators (zip and repeat) you can use a generator (works both in 2 & 3):

from collections import OrderedDict
unique_list = list(OrderedDict((element, None) for element in my_list))
Benjamin Loison
5,7324 gold badges19 silver badges37 bronze badges
answered May 10, 2016 at 9:49
3

If it's clarity you're after, rather than speed, I think this is very clear:

def sortAndUniq(input):
 output = []
 for x in input:
 if x not in output:
 output.append(x)
 output.sort()
 return output

It's O(n^2) though, with the repeated use of not in for each element of the input list.

answered Jan 26, 2009 at 14:16
0
2

> but I don't know how to retrieve the list members from the hash in alphabetical order.

Not really your main question, but for future reference Rod's answer using sorted can be used for traversing a dict's keys in sorted order:

for key in sorted(my_dict.keys()):
 print key, my_dict[key]
 ...

and also because tuple's are ordered by the first member of the tuple, you can do the same with items:

for key, val in sorted(my_dict.items()):
 print key, val
 ...
answered Jan 26, 2009 at 15:22
-1

For the string data

output = []
 def uniq(input):
 if input not in output:
 output.append(input)
print output 
Benjamin Loison
5,7324 gold badges19 silver badges37 bronze badges
answered Jun 26, 2013 at 9:36

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.