Bob
Bob

Reputation: 1396

Adding Elements from a List of Lists to a Set?

I'm attempting to add elements from a list of lists into a set. For example if I had

new_list=[['blue','purple'],['black','orange','red'],['green']]

How would I receive

new_set=(['blue','purple'],['black','orange','red'],['green'])

I'm trying to do this so I can use intersection to find out what elements appear in 2 sets. I thought this would work...

results=set()
results2=set()
for element in new_list:
    results.add(element)

for element in new_list2:
    results2.add(element)
results3=results.intersection(results2)

but I keep receiving:

TypeError: unhashable type: 'list' 

for some reason.

Upvotes: 0

Views: 1683

Answers (3)

abarnert
abarnert

Reputation: 365717

How would I receive

new_set=(['blue','purple'],['black','orange','red'],['green'])

Well, despite the misleading name, that's not a set of anything, that's a tuple of lists. To convert a list of lists into a tuple of lists:

new_set = tuple(new_list)

Maybe you wanted to receive this?

new_set=set([['blue','purple'],['black','orange','red'],['green']])

If so… you can't. A set cannot contain unhashable values like lists. That's what the TypeError is telling you.

If this weren't a problem, all you'd have to do is write:

new_set = set(new_list)

And anything more complicated you write will have exactly the same problem as just calling set, so there's no tricky way around it.


Of course you can have a set of tuples, since they're hashable. So, maybe you wanted this:

new_set=set([('blue','purple'),('black','orange','red'),('green')])

That's easy too. Assuming your inner lists are guaranteed to contain nothing but strings (or other hashable values), as in your example it's just:

new_set = set(map(tuple, new_list))

Or, if you use a sort-based set class, you don't need hashable values, just fully-ordered values. For example:

new_set = sortedset(new_list)

Python doesn't come with such a thing in the standard library, but there are some great third-party implementations you can install, like blist.sortedset or bintrees.FastRBTree.

Of course sorted-set operations aren't quite as fast as hash operations in general, but often they're more than good enough. (For a concrete example, if you have 1 million items in the list, hashing will make each lookup 1 million times faster; sorting will only make it 50,000 times faster.)


Basically, any output you can describe or give an example of, we can tell you how to get that, or that it isn't a valid object you can get… but first you have to tell us what you actually want.


By the way, if you're wondering why lists aren't hashable, it's just because they're mutable. If you're wondering why most mutable types aren't hashable, the FAQ explains that.

Upvotes: 3

Gopher
Gopher

Reputation: 21

Make the element a tuple before adding it to the set:

new_list=[['blue','purple'],['black','orange','red'],['green']]
new_list2=[['blue','purple'],['black','green','red'],['orange']]

results=set()
results2=set()
for element in new_list:
    results.add(tuple(element))

for element in new_list2:
    results2.add(tuple(element))

results3=results.intersection(results2)
print results3

results in:

set([('blue', 'purple')])

Set elements have to be hashable.

  • for adding lists to a set, instead use tuple
  • for adding sets to a set, instead use frozenset

Upvotes: 1

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250951

Convert the inner lists to tuples, as sets allow you to store only hashable(immutable) objects:

In [72]: new_list=[['blue','purple'],['black','orange','red'],['green']]

In [73]: set(tuple(x) for x in new_list)
Out[73]: set([('blue', 'purple'), ('black', 'orange', 'red'), ('green',)])

Upvotes: 4

Related Questions