David - 10 months ago 71

Python Question

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())]
```