David David - 6 months ago 24
Python Question

list(set) for nested lists?

I am currently working on a module that will compute the angle between a vector and the normal of a plane.

Anyhow to satisfy the conditions of computing the normal to the plane, I need 3 points in R3.

I have found a way to do this by converting the list elements to strings, however this complicates the code downstream. The following block of code aims to satisfy this condition. List t2 contains the strings and works well downstream, however I wish to work with a nested list (t1).

t1,t2=[],[] #B3
for i in range(0, len(s)):
t1.append([s[i][0][0],s[i][2][4]])

t2.append(s[i][0][0]+s[i][2][4])
u,j,k=list(set(t2)),[],[]
for item in u:
j.append(t2.count(item))
if len(u) == len(j):
for i in range(0, len(u)):
if j[i] >= 3:
k.append([u[i]])

#For additional clarity:
List t1 looks as follows:
[['[7,', '158,'],
['[7,', '158,'],
['[51,', '158,'],
['[51,', '158,'],
['[51,', '158,'],
['[51,', '161,'],
['[51,', '161,'],
['[51,', '161,'],
['[298,', '114,'],
['[808,', '138,'],
['[808,', '138,']...


So within t1 if there exists 3 or more lists containing equivalent elements (such as ['[51,', '158,']) I wish to append these. The problem is that the set() does not work with nested lists.

Is there a way around this?
Cheers

Answer

In case that you want to get all the lists with three or more instances and preserve the ordering you can use OrderedDict where keys are tuples and values are counts:

from collections import OrderedDict

t1 = [
    ['[7,', '158,'],
    ['[7,', '158,'],
    ['[51,', '158,'],
    ['[51,', '158,'],
    ['[51,', '158,'],
    ['[51,', '161,'],
    ['[51,', '161,'],
    ['[51,', '161,'],
    ['[298,', '114,'],
    ['[808,', '138,'],
    ['[808,', '138,']
]

d = OrderedDict()
for x in t1:
    t = tuple(x)
    d[t] = d.get(t, 0) + 1

[list(k) for k, v in d.items() if v >= 3] # [['[51,', '158,'], ['[51,', '161,']]

If ordering is not important you could use Counter:

from collections import Counter
from itertools import takewhile

c = Counter(tuple(x) for x in t1)
[list(k) for k, v in takewhile(lambda x: x[1] >= 3, c.most_common())]
Comments