Reputation: 623
I have a little code that takes a list of objects, and only outputs the items in the list that are unique.
This is my code
def only_once(a):
return [x for x in a if a.count(x) is 1]
My teacher requires us to use sets for this function though. Can someone show me what I can do?
My code has to take an input such as a=[1,4,6,7,3,2,4,5,7,5,6], and output [1, 3, 2]. Has to retain it's order also.
Upvotes: 3
Views: 368
Reputation: 353069
[I'm assuming that you're also user1744238 and user1744316 -- please pick a username and stick to it, that way it's easier to check to see what variants of a question you've asked and what you've already tried.]
One set-based approach is to use two sets as a counter. You only care about whether you've seen something once or more than once. For example, here's an easy-to-explain approach:
once
and more
. once
. once
and add it to more
. once
. once
set so you don't output the same element twice.This gives me:
In [49]: f([1,4,6,7,3,2,4,5,7,5,6])
Out[49]: [1, 3, 2]
Upvotes: 3
Reputation: 176780
If you need to remove any item that is in the list more than once, not just occurences after the first, you can use:
# without using generators / comprehensions
def only_once(iterable):
seen = set()
duplicates = set()
for item in iterable:
if item in seen:
duplicates.add(item)
seen.add(item)
result = []
for item in iterable:
if item not in duplicates:
result.append(item)
return result
For general order-preserving duplicate elimination, see unique_everseen
in the itertools recipes:
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in ifilterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
Upvotes: 3
Reputation: 89017
To clarify, what you want is a set of items that appear once, and only once.
The best option here is to use collections.Counter()
, as it means you only count the items once, rather than once per item, greatly increasing performance:
>>> import collections
>>> {key for key, count in collections.Counter(a).items() if count == 1}
{1, 2, 3}
We simply replace the square brackets with curly braces to signify a set comprehension over a list comprehension, to get a set of results.
Upvotes: 3