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.

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
Sign up to request clarification or add additional context in comments.

8 Comments

This does not work if your myList has unhashable objects.
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?
@CorneliuZuzu Removing duplicates with set() changes order, so you have to do it this way
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]
@user3667349 The "keep order" clause was not a part of the original question, it was added by the Colonel Panic edit in 2015.
|
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)))

3 Comments

This can also be expressed as [e for e, _ in groupby(sortedList)]
This is O(n) rather than O(n log n) right?
FWIW something similar was added to the list of recipes from the documentation for itertools.
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))

Comments

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.

Comments

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
    ...

Comments

-1

For the string data

output = []

    def uniq(input):
        if input not in output:
           output.append(input)
print output     

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.