I have a list `l` in the following way:

``l = [([1, 0.0, 50.0, 2, 0.0, 50.0], [1, 1.9, 1]),([1, 0.0, 50.0, 2, 0.0, 50.0], [2, 1.9, 1])]``

I want to transform this list such that the new structure is as follows:

``goal = [([1, 0.0, 50.0], [2, 0.0, 50.0], [1, 1.9, 1]), ([1, 0.0, 50.0], [2, 0.0, 50.0], [2, 1.9, 1])]``

Namely, that the first list in each tuple gets unraveled to sublists of length 3.

I tried it the following way but got stuck as the various transformations give back numpy arrays and it turns out messy.

Additionally, this operation could potentially take place on large variants of l so should be performance friendly/in-place(?).

``terms = np.array(l)[:,0][np.split(np.array(i), 2) for i in terms]``

In my comment I argued against the use of `np.array` for this, since

``````In [241]: np.array(l)
Out[241]:
array([[[1, 0.0, 50.0, 2, 0.0, 50.0], [1, 1.9, 1]],
[[1, 0.0, 50.0, 2, 0.0, 50.0], [2, 1.9, 1]]], dtype=object)
``````

is an object array. However the array version can make splitting a list easy, with reshape

``````In [240]: [np.array(x[0]+x[1]).reshape(-1,3).tolist() for x in l]
Out[240]:
[[[1.0, 0.0, 50.0], [2.0, 0.0, 50.0], [1.0, 1.9, 1.0]],
[[1.0, 0.0, 50.0], [2.0, 0.0, 50.0], [2.0, 1.9, 1.0]]]
``````

Add `[tuple(n...` if it must be tuples, not lists.

I'm doing a couple of tricks. Since the second item has the same length as the desired split (3), I'm just concatenating them at the start, rather worry about doing so later. And then array reshape followed by `tolist` effectively splits the array.

``````In [246]: np.reshape(x[0]+x[1],(-1,3))
Out[246]:
array([[  1. ,   0. ,  50. ],
[  2. ,   0. ,  50. ],
[  1. ,   1.9,   1. ]])
``````

This depends on being able to split the sublists evenly by 3.

The array round trip is probably slower than the equivalent `itertools` code.

`in-place` won't work because you have a list of tuples. You can replace those tuples, but you can't modify them. If they were lists, you could splice in the split like this:

``````In [248]: x
Out[248]: ([1, 0.0, 50.0, 2, 0.0, 50.0], [1, 1.9, 1])
In [249]: xl=list(x)

In [250]: xl[0:1] = [xl[0][:3],xl[0][3:]]   # or the split of your choice
In [251]: xl
Out[251]: [[1, 0.0, 50.0], [2, 0.0, 50.0], [1, 1.9, 1]]
``````

Often it is more convenient to create new lists and tuples than to change things in place. Copying a list of lists just means making a new list of the same pointers.

Since it is ok to slice off the end of a list `@Kasramvd's` `islice` version can be simplified to:

``````[tuple([i[t:t+3]  for i in sub for t in range(0, len(i), 3)]) for sub in l]
``````

You can use `itertools.chain` within a list comprehension:

``````In [23]: from itertools import chain

In [24]: [tuple(chain.from_iterable((i[:3], i[3:]) if len(i) > 3 else [i] for i in sub)) for sub in l]
Out[24]:
[([1, 0.0, 50.0], [2, 0.0, 50.0], [1, 1.9, 1]),
([1, 0.0, 50.0], [2, 0.0, 50.0], [2, 1.9, 1])]
``````

As a general way you can use `itertools.islice` in order to slice your sub lists to triples:

``````In [37]: [tuple(list(islice(i,t,t+3)) if len(i) > 3 else i for i in sub for t in range(0, len(i), 3)) for sub in l]
Out[37]:
[([1, 0.0, 50.0], [2, 0.0, 50.0], [1, 1.9, 1]),
([1, 0.0, 50.0], [2, 0.0, 50.0], [2, 1.9, 1])]
``````

Top