0

I have a list (e.g. a = [1, 2, 3, [1, 2, 4]]) and I want to create a set from its elements at the lowest levels of the nesting (in the previous example, to obtain setA = {1, 2, 3, 4}).

Running set(a) gives me the error:

TypeError: unhashable type: 'list'

What should I do to obtain such a set?

Robb1
  • 4,587
  • 6
  • 31
  • 60

2 Answers2

2

You will have to first flatten the irregularly nested list. Below are 2 solutions that will handle any depth, irregularly nested lists.

Using collections

Try collections for flattening the irregular deep nested list -

import collections

def flatten(x):
    if isinstance(x, collections.Iterable):
        return [a for i in x for a in flatten(i)]
    else:
        return [x]
    
a = [1, 2, 3, [1, [2, 4]]] #Irregular deep nested list
out = set(flatten(a))
out
{1, 2, 3, 4}

More details here.


Using recursion

For lists that are nested deeper, you can use recursion -

def flatten(S):
    if S == []:
        return S
    if isinstance(S[0], list):
        return flatten(S[0]) + flatten(S[1:])
    return S[:1] + flatten(S[1:])

a = [1, 2, 3, [1, [2, 4]]] #Irregular deep nested list
out = set(flatten(a))
out
{1, 2, 3, 4}

More details here.


One-liner with recursion

If like me, you prefer using one-liners, try this lambda function with recursion -

f = lambda *n: (e for a in n for e in (f(*a) if isinstance(a, (tuple, list)) else (a,)))

out = set(f(a))
out
{1, 2, 3, 4}

More details here.

Akshay Sehgal
  • 18,741
  • 3
  • 21
  • 51
1

Here is my suggestion. It uses recursion and works with any level of nested structure:

import collections

def getset(l):
    res=set()
    for i in l:
        if isinstance(i, collections.Iterable):
            res=res.union(getset(i))
        else:
            res.add(i)
    return res

getset(a)
#{1,2,3,4}

getset([1, 2, 3, [4, 5, [10, 20, [100, 200]]], [12, 14, [16, 18]]])
#{1, 2, 3, 4, 5, 100, 200, 10, 12, 14, 16, 18, 20}
IoaTzimas
  • 10,538
  • 2
  • 13
  • 30