Chu - 1 year ago 39

Python Question

I know the topic is really hard to understand but I don't know how to describe my problem in one sentence...T^T

Here is what I'm trying to do.

I have a set of 1-dimensional points in three categories.

`A = [[0,1], [0,2], [0,3], [1,1], [2,1], [3,2], [3,3], [4,2], [4,3], [5,3], [6,3]]`

First number is x-coordinate and second number is label in each [ ]

And I want to insert a cut point into every pair of adjacent points [x1, L1], [x2, L2] if at least one of them has more than one kinds of label and L2 belongs to those categories that differ from L1.;;;

For example,

`[0,1], [0,2], [0,3]`

they are all on x = 0 but there are three kinds of labels

`[1,1]`

belongs to only one categories, so I would like to add a cut point x=0.5 in the middle of 0 and 1.

`3 x`

2 x

1 x 1

x

0-x-1-

but like

`[1,1] and [2,1]`

they both has only one and identical label, there is no need to add a cut point here.

So the result should be

`[0.5, 2.5, 3.5, 4.5]`

and maybe looks like this

`3 x x 3 x 3 x 3 3 <--Label`

2 x x 2 x 2 x <--Label

1 x 1 1 x x x <--Label

x x x x

-0-x-1---2-x-3-x-4-x-5---6--- <--X-axis

0.5 2.5 3.5 4.5 <--Cut points

The code I want to write will looks like this form

`A = [[0,1], [0,2], [0,3], [1,1], [2,1], [3,2], [3,3], [4,2], [4,3], [5,3], [6,3]]`

X = []

for a in A:

X.append(a[0])

X = sorted(list(set(X)))

labels = [[1], [2], [3]]

group = []

for i in range(len(labels)):

group.append([])

for a in A:

for i in range(3):

if a[1] in labels[i]:

group[i].append(a[0])

cutpoints = []

for i, x in enumerate(X):

for j in range(len(group)):

if x in group[j] and (X[i+1] in group[ other than j ]):

cutpoints.append((x+X[i+1])/2)

But I stuck at the part "other than j"

In this case there are only 3 categories so maybe I can do that manually but I'm looking for a more clever way to do it so I don't need to rewrite this part every time I meet a new data with different number of categories.

Is there any function I can use to do the "other than j" operation??

Any comment or answer will be appreciated.

Thanks in advance T^T

Answer Source

This is sort of a weird problem you've got, but here's a functional way to do.

```
from itertools import groupby
```

`groupby`

will let us easily merge your X coordinates, assuming the array is pre-sorted by them.

```
l = [(i, [x[1] for x in g]) for i, g in groupby(A, lambda x: x[0])]
```

This looks a bit daunting, but is conceptually pretty easy. The `groupby`

pulls together all the things that share an X, and the inner list comprehension just dumps the X values out:

```
l
[(0, [1, 2, 3]),
(1, [1]),
(2, [1]),
(3, [2, 3]),
(4, [2, 3]),
(5, [3]),
(6, [3])]
```

Then if we group each together with the next element using `zip`

we can just pick out the pairs that meet your criteria and get the midpoint between them:

```
[(i1+i2) / 2.
for (i1, l1), (i2, l2)
in zip(l, l[1:])
if l1 != l2 or len(l1) > 1]
[0.5, 2.5, 3.5, 4.5]
```