I have the following list of lists.
If last sublist has len>1:
x = [[0], [1, 2, 3], [4, 5], [6], [7, 8, 9], [10, 11, 12, 13], [15], [16, 17, 18]]
expected_output = [[0, 1, 2, 3], [4, 5], [6, 7, 8, 9], [10, 11, 12, 13], [15, 16, 17, 18]]
If last sublist has len==1:
x = [[0], [1, 2, 3], [4, 5], [6], [7, 8, 9], [10, 11, 12, 13], [15], [16, 17, 18], [19]]
expected_output = [[0, 1, 2, 3], [4, 5], [6, 7, 8, 9], [10, 11, 12, 13], [15, 16, 17, 18], [19]]
I'm trying to merge the sublists of length 1 with the next sublist.
If the last sublist length is one, I want to leave it as is.
I tried writing the following code.
xt = []
for i in range(len(x)-1):
if len(x[i]) == 1:
xt.append(x[i]+x[i+1])
# del x[i+1]
if len(x[i])>1:
xt.append(x[i])
print(xt)
Try this :
def ref1(l):
con = 0
l2 = []
while con<len(l)-1:
if len(l[con])==1:
l2.append(l[con]+l[con+1])
con +=2
else:
l2.append(l[con])
con+=1
if len(l[-1])==1:
l2.append(l[-1])
print(l2)
ref1([[0], [1, 2, 3], [4, 5], [6], [7, 8, 9], [10, 11, 12, 13], [15], [16, 17, 18]])
# OUTPUT : [[0, 1, 2, 3], [4, 5], [6, 7, 8, 9], [10, 11, 12, 13], [15, 16, 17, 18]]
ref1([[0], [1, 2, 3], [4, 5], [6], [7, 8, 9], [10, 11, 12, 13], [15], [16, 17, 18], [19]])
# OUTPUT : [[0, 1, 2, 3], [4, 5], [6, 7, 8, 9], [10, 11, 12, 13], [15, 16, 17, 18], [19]]
Code Analysis
xt = []
for i in range(len(x)-1):
if len(x[i]) == 1:
xt.append(x[i]+x[i+1])
This means you are adding the next sublist before visiting it
# del x[i+1]
if len(x[i])>1:
xt.append(x[i])
and this doesn't have a history of if the sublist has already been merged.
print(xt)
Advice
Visit the list the other way around, and check each time if the previous list is of length 1.
OR
Keep tab of if the previous action was a merge.
TO OP
If you need more help, please shout
Related
I have the following list, let's call it R:
[(array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]),
array([100, 101, 102])),
(array([[10, 11, 12],
[13, 14, 15],
[16, 17, 18]]),
array([103, 104, 105]))]
I want to be able to delete columns of R in a for loop, based on an index i. For example, if i = 3, the 3rd column should be deleted, which should result in the following new, say R1:
[(array([[1, 2],
[4, 5],
[7, 8]]),
array([100, 101])),
(array([[10, 11],
[13, 14],
[16, 17]]),
array([103, 104]))]
I have zero experience with handling such multi dimensional arrays, so I am unsure how to use numpy.delete(). My actual list R is pretty big, so I would appreciate if someone can suggest how to go about the loop.
You can use np.delete with col==2 and axis=-1.
# if your 'list' be like below as you say in the question :
print(lst)
# [
# array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]]),
# array([100, 101, 102]),
# array([[10, 11, 12],
# [13, 14, 15],
# [16, 17, 18]]),
# array([103, 104, 105])
# ]
for idx, l in enumerate(lst):
lst[idx] = np.delete(l, 2, axis=-1)
print(lst)
Output:
[
array([[1, 2],
[4, 5],
[7, 8]]),
array([100, 101]),
array([[10, 11],
[13, 14],
[16, 17]]),
array([103, 104])
]
Creating input array like in the question:
import numpy as np
lst = [[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]],
[100, 101, 102],
[[10, 11, 12],
[13, 14, 15],
[16, 17, 18]],
[103, 104, 105]
]
lst = [np.array(l) for l in lst]
Update base comment, If you have a tuple of np.array in your list, you can try like below:
lst = [
(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), np.array([100, 101, 102])),
(np.array([[10, 11, 12], [13, 14, 15], [16, 17, 18]]), np.array([103, 104, 105]))
]
for idx, tpl in enumerate(lst):
lst[idx] = tuple(np.delete(l, 2, axis=-1) for l in tpl)
print(lst)
Output:
[
(array([[1, 2],
[4, 5],
[7, 8]]),
array([100, 101])
),
(array([[10, 11],
[13, 14],
[16, 17]]),
array([103, 104]))
]
This question already has answers here:
What is the best way to perform an anti-transpose in python?
(4 answers)
Closed 4 months ago.
Does anyone could tell me how to reorder the matrix:
[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]]
To:
[[15, 10, 5],
[14, 9, 4],
[13, 8, 3],
[12, 7, 2],
[11, 6, 1]]
Since you have tagged the question numpy, I surmise that those are numpy matrix, and you are looking for a numpy solution (otherwise, if those are lists, Ann's zip is the correct solution).
For numpy you can
M[::-1,::-1].T
Example
M=np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
M[::-1,::-1].T
returns
array([[15, 10, 5],
[14, 9, 4],
[13, 8, 3],
[12, 7, 2],
[11, 6, 1]])
as expected
I'd suggest using numpy, like so:
import numpy as np
matrix = np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]])
transformed_matrix = matrix[::-1].T[::-1]
# array([[15, 10, 5],
# [14, 9, 4],
# [13, 8, 3],
# [12, 7, 2],
# [11, 6, 1]])
matrix[::-1] gives you the original matrix in reverse order (i.e. [11, 12, 13...] first and [1, 2, 3...] last).
Taking the transpose of that with .T rotates the matrix about - swapping rows and columns.
Lastly, indexing the transpose with [::-1] reverses the order, putting [15, 14, 13...] first and [5, 4, 3...] last.
Here is how you can use the zip() method to transpose your matrix:
m = [[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]]
print([list(i)[::-1] for i in zip(*m)][::-1])
Output:
[[15, 10, 5],
[14, 9, 4],
[13, 8, 3],
[12, 7, 2],
[11, 6, 1]]
The index [::-1] reverses the array.
I have matrix A of shape (p, q, r, r) and another matrix I of shape (r, s). I want to select only s of the r elements from the last dimension of A, so that the shape of the new matrix becomes (p, q, r, s).
To simplify (ignoring the first two dimensions), let
>>> A
array([[5, 2, 5, 7],
[2, 6, 4, 3],
[4, 2, 3, 9],
[6, 2, 4, 3]])
>>> I
array([[1, 2],
[2, 2],
[3, 1],
[2, 1]])
I want the matrix
array([[2, 5],
[4, 4],
[9, 2],
[4, 2]])
How can I do it? A[..., I] gives a (4, 4, 2) matrix, selecting elements located at I from each row. I can solve the problem by
>>> c = np.arange(4)
>>> A[..., I][c, c, :]
array([[2, 5],
[4, 4],
[9, 2],
[4, 2]])
But I think it requires a lot of computation. Is there any more efficient way to solve this issue?
Edit:
For higher dimensional example, consider I to be same as before, and
A
array([[[[12, 15, 6, 12],
[16, 16, 4, 17],
[ 6, 19, 10, 9],
[ 5, 11, 18, 17]],
[[13, 12, 5, 6],
[12, 7, 5, 4],
[ 9, 19, 12, 4],
[15, 4, 16, 7]],
[[13, 6, 5, 17],
[ 8, 4, 10, 9],
[ 3, 13, 16, 4],
[ 3, 3, 4, 4]]],
[[[ 8, 3, 8, 18],
[ 7, 11, 8, 7],
[10, 8, 14, 9],
[ 8, 12, 16, 5]],
[[ 9, 10, 10, 7],
[11, 6, 10, 6],
[16, 19, 10, 14],
[ 9, 13, 13, 19]],
[[10, 8, 19, 12],
[ 9, 10, 17, 19],
[ 4, 11, 12, 14],
[ 8, 5, 16, 10]]]])
Expected output:
array([[[[15, 6],
[ 4, 4],
[ 9, 19],
[18, 11]],
[[12, 5],
[ 5, 5],
[ 4, 19],
[16, 4]],
[[ 6, 5],
[10, 10],
[ 4, 13],
[ 4, 3]]],
[[[ 3, 8],
[ 8, 8],
[ 9, 8],
[16, 12]],
[[10, 10],
[10, 10],
[14, 19],
[13, 13]],
[[ 8, 19],
[17, 17],
[14, 11],
[16, 5]]]]
A[...,I][..., c, c, :] yield this result
Since you're using integer array indexing, you'll need to specify which rows you want to select those columns from:
A[np.arange(A.shape[0])[:,None], I]
array([[2, 5],
[4, 4],
[9, 2],
[4, 2]])
Or you also have np.take_along_axis:
np.take_along_axis(A, I, 1)
For a larger array of shape (p, q, r, r), take full slices along the front axes, and use broadcasting in a similar way:
A[...,np.arange(A.shape[2])[:,None],I]
array([[[[15, 6],
[ 4, 4],
[ 9, 19],
[18, 11]],
[[12, 5],
[ 5, 5],
[ 4, 19],
[16, 4]],
...
I have lists of the following form:
a = [[1, 2, 3, [4, 5, 6, 7, [8, 9, [10, 11, 12]]]]]
These lists can be of varying "depth" and can have a varying number of elements at each level (i.e. the outer list can have a different number of elements than its inner).
How can I convert this into a list of lists with a depth of 1:
a = [[1, 2, 3], [4, 5, 6, 7], [8, 9], [10, 11, 12]]
You can try a recursive approach:
def listOfList(lst):
b = []
def recurs(lst):
c = []
for i in lst:
if isinstance(i, list):
if c:
b.append(c)
c = []
recurs(i)
else:
c.append(i)
if c: b.append(c)
return b
return recurs(lst)
Example:
>>> a = [[1, 2, 3, [4, 5, 6, 7, [8, 9, [10, 11, 12]]]]]
>>> listOfList(a)
[[1, 2, 3], [4, 5, 6, 7], [8, 9], [10, 11, 12]]
>>> a = [[[1, 2, 3, [4, 5, 6, 7, [8, 9, [10, 11, 12, [13, 14]]]]]]]
>>> listOfList(a)
[[1, 2, 3], [4, 5, 6, 7], [8, 9], [10, 11, 12], [13, 14]]
This is also useful in case the list is not nested in proper way:
>>> a = [[[1, 2, 3, [4, 5, 6, 7, [8, 9, [10, 11, 12, [13, 14]]]]]], [15, 16]]
>>> listOfList(a)
[[1, 2, 3], [4, 5, 6, 7], [8, 9], [10, 11, 12], [13, 14], [15, 16]]
>>> a = [[[1, 2, 3, [4, 5, 6, 7, [8, 9, [10, 11, 12, [13, 14]]]]]], [15, 16], 17, 18, 19]
>>> listOfList(a)
[[1, 2, 3], [4, 5, 6, 7], [8, 9], [10, 11, 12], [13, 14], [15, 16], [17, 18, 19]]
a = [[1, 2, 3, [4, 5, 6, 7, [8, 9, [10, 11, 12]]]]]
new_a = []
while isinstance(a, list):
last = a.pop()
if a:
new_a.append(a)
a = last
print(new_a)
You just need a recursion to ergodic your nested list.
def func(c):
d = []
if isinstance(c[-1], list):
return [c[:-1], *func(c[-1])]
else:
return [c]
print(func(a))
And the output is:
>>> [[], [1, 2, 3], [4, 5, 6, 7], [8, 9], [10, 11, 12]]
There is a empty list at first because the top level of your lists only have one item. To convert it as you want, you can use another for loop:
for b in a:
print(func(b))
Then the result is what you want:
>>> [[1, 2, 3], [4, 5, 6, 7], [8, 9], [10, 11, 12]]
i = [1,2,3,4,5,6,7,8,9,10]
def ndiv(l,n):
return [l[s:e] for s, e in zip(range(0,len(l)+1,n),xrange(n,len(l)+1,n))]
for i in xrange(1,15,1):
print "CLUSTER {}".format((ndiv(l,i)))
#print
CLUSTER [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17]]
CLUSTER [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14], [15, 16]]
CLUSTER [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]
CLUSTER [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
CLUSTER [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]
CLUSTER [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
CLUSTER [[1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14]]
CLUSTER [[1, 2, 3, 4, 5, 6, 7, 8], [9, 10, 11, 12, 13, 14, 15, 16]]
CLUSTER [[1, 2, 3, 4, 5, 6, 7, 8, 9]]
Coding up to now. After dividing, the remaining values are not shown omitted.But I want to have the prices shown after we split them(EX.if divide '3' ->before [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]] / after [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15],[16],[17] ).How can I divide and then show the remaining numbers one by one?
You can compute 2 lists, one that splits contains batches of n and the other that maps remaining elements into one element list and finally merge them together
>>> l = list(xrange(1,18))
>>> def ndiv(l,n):
... return [l[i:i+n] for i in xrange(0,len(l)//n*n, n)] + [[e] for e in l[len(l)//n*n:]]
...
>>> ndiv(l, 5)
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16], [17]]