(Python) I have the following array
x=[1,2,3,4,5,6]
and I want this one
x=[[1,2],[2,3],[3,4],[4,5],[5,6]]
I used this function
def split(arr, size):
arrs = []
while len(arr) > size:
pice = arr[:size]
arrs.append(pice)
arr = arr[size:]
arrs.append(arr)
return arrs
But it only generates this
x=[[1,2],[3,4],[5,6]]
I suppose you want to develop your own code and not use libraries or built-in functions.
Your code is fine.
There's just one simple mistake: change the slice index from size to 1 in this line arr = arr[size:], where 1 means size - (size-1)
def split(arr, size):
arrs = []
while len(arr) > size:
pice = arr[:size]
arrs.append(pice)
arr = arr[1:]
arrs.append(arr)
return arrs
output:
[[1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]
It also works for other sizes:
print split(x, 3)
print split(x, 4)
[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]
[[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]]
loop your array with index, then put [index : index+size] as one element of new array.
The codes will be like:
x=[1,2,3,4,5,6]
size = 2
print([x[index:index+size] for index in range(0, len(x)-size+1)])
size = 4
print([x[index:index+size] for index in range(0, len(x)-size+1)])
Output:
[[1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]
[[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]]
[Finished in 0.189s]
or use zip() with size>1.
x=[1,2,3,4,5,6]
size = 2
print( [item for item in zip( *[x[index:len(x)+index-1] for index in range(0, size)])])
size = 4
print( [item for item in zip( *[x[index:len(x)+index-1] for index in range(0, size)])])
Output:
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
[(1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6)]
[Finished in 0.284s]
You can use windowed() function from the more_itertools module.
from more_itertools import windowed
x = list(windowed(x, 2))
You can install it using pip
pip install more-itertools
Try this :
def split(arr, size):
return [x[i:i+size] for i in range(0,len(x)-size+1)]
a = [1,2,3,4,5]
answer = list(map(list, zip(a, a[1:])))
print(answer)
You can use fancy indexing when using NumPy. This will require x to be converted to a numpy array. You will also need to create an array of incidences labeled ind below
x=[1,2,3,4,5,6]
x = np.array(x)
ind = np.arange(len(x)-1)[:,None] + np.arange(2)
x[ind]
array([[1, 2],
[2, 3],
[3, 4],
[4, 5],
[5, 6]])
Related
I need to create a 2-D numpy array using only list comprehension, but it has to follow the following format:
[[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7]]]
So far, all I've managed to figure out is:
two_d_array = np.array([[x+1 for x in range(3)] for y in range(5)])
Giving:
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
Just not very sure how to change the incrementation. Any help would be appreciated, thanks!
EDIT: Accidentally left out [3, 4, 5] in example. Included it now.
Here's a quick one-liner that will do the job:
np.array([np.arange(i, i+3) for i in range(1, 6)])
Where 3 is the number of columns, or elements in each array, and 6 is the number of iterations to perform - or in this case, the number of arrays to create; which is why there are 5 arrays in the output.
Output:
array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7]])
Change the code, something like this can work:
two_d_array = np.array([[(y*3)+x+1 for x in range(3)] for y in range(5)])
>>> [[1,2,3],[4,5,6],...]
two_d_array = np.array([[y+x+1 for x in range(3)] for y in range(5)])
>>> [[1,2,3],[2,3,4],...]
You've got a couple of good comprehension answers, so here are a couple of numpy solutions.
Simple addition:
np.arange(1, 6)[:, None] + np.arange(3)
Crazy stride tricks:
base = np.arange(1, 8)
np.lib.stride_tricks.as_strided(base, shape=(5, 3), strides=base.strides * 2).copy()
Reshaped cumulative sum:
base = np.ones(15)
base[3::3] = -1
np.cumsum(base).reshape(5, 3)
I have a list of lists that include dominos(those are also a list of two integers) and i need to find the index of one of the domino
example:
list_of_hand = [[[2, 5], [5, 5], [6, 5], [6, 4]], [[3, 2], [4, 5], [4, 4], [6, 1]]]
This list is two lists that includ all the dominos that a player have in is hand.
How can i find the index of the domino [6, 5]?
You could use a simple function to search through the sublists:
x = [[[2, 5], [5, 5], [6, 5], [6, 4]], [[3, 2], [4, 5], [4, 4], [6, 1]]]
def hand_search(L, domino):
for s in L:
if domino in s:
return (L.index(s), s.index(domino))
return -1
print(hand_search(x, [6,5]))
print(hand_search(x, [6,1]))
Output:
(0, 2) # 0 is the player, 2 is the position in their hand
(1, 3) # 1 is the player, 3 is the position in their hand
This would scale to as many players as you want, as long as the nesting is the same.
One method would be to use the enumerate(PEP 279) function in loops like this:
def search(l,domino):
for m,i in enumerate(l):
for n,j in enumerate(i):
if domino == j:
return(m,n)
return("No match.")
>>> search(list_of_hand,[6,5])
(0, 2)
Alternatively you can keep everything in dictionaries:
dominos, hands = {}, {}
def give(d, h):
hands.setdefault(h, []).append(d)
dominos.update({d:h})
give( (6,5), 1 )
give( (2,5), 1 )
give( (3,2), 2 )
give( (5,5), 2 )
print hands # {1: [(6, 5), (2, 5)], 2: [(3, 2), (5, 5)]}
print dominos # {(2, 5): 1, (3, 2): 2, (6, 5): 1, (5, 5): 2}
print hands[2] # [(3, 2), (5, 5)]
print dominos[(6,5)] # 1
You can use dict with enumerate :
Here is example with two [6,5]
list_of_hand = [[[2, 5], [5, 5], [6, 5], [6, 4]], [[3, 2], [4, 5], [4, 4], [6, 1],[6,5]]]
def find_dominos(list_data,value):
index_v={}
for i,j in enumerate(list_data):
for sub,index_sub in enumerate(j):
if value==index_sub:
if tuple(value) not in index_v:
index_v[tuple(value)]=[(i,sub)]
else:
index_v[tuple(value)].append((i,sub))
return index_v
print(find_dominos(list_of_hand,[6,5]))
output:
{(6, 5): [(0, 2), (1, 4)]}
I have a list of matrix indices and want to access a matrix by these indices.
Example:
indices = [(2, 0), (2, 1), (2, 2)]
mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
mat[indices] = 0
This should result in [[1, 2, 3], [4, 5, 6], [0, 0, 0]], but unfortunately I always get "list indices must be integers, not list".
EDIT
As user2357112 suggests in his comment I tried the following now:
mat = numpy.array(mat)
indices = numpy.array(indices)
mat[indices] = 0
But unfortunately the whole matrix is filled with 0 now.
indices is a regular list of tuples and can't be used to get an element of your regular mat. What you can do is iterate over your list to get your indices:
for x, y in indices:
mat[x][y] = 0
If you want to use numpy methods, you need to create a numpy array. Indeed, np.array structure allows to use tuple to access to an element:
mat = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
for item in indices:
mat[item] = 0
You can use zip(*indices) to access a numpy array by
an indices list:
import numpy as np
indices = [(2, 0), (2, 1), (2, 2)]
mat = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>> mat[zip(*indices)]
array([7, 8, 9])
>> mat[zip(*indices)] = 0
>> mat
array([[1, 2, 3],
[4, 5, 6],
[0, 0, 0]])
This question already has answers here:
Matrix Transpose in Python [duplicate]
(19 answers)
Closed 8 years ago.
I am trying to find a way to transpose a matrix, for example for:
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
it would change the matrix to:
[[1, 4, 7],
[2, 5, 8],
[3, 6, 9]]
So far, I tried several things but it never worked. I tried:
def transpose_matrix(matrix): # this one doesn't change the matrix at all
zip(*matrix)
return matrix
or
def transpose_matrix(matrix):
map(list, zip(*matrix))
return matrix
or
def transpose_matrix(matrix): # this one returns an empty list []
print(list(zip(*matrix)))
I want to code it without using external library such as numpy.
After that, it returns the result to this menu and use the transposed matrix for upcoming option (not shown):
def menu(matrix):
print('choose option')
loop = True
while loop:
print('''
1-display matrix
7-transpose it
8-other option
0-back
''')
choi = input('cchoice:')
if choi =='1':
print('\n'.join([' '.join(map(str, row)) for row in matrix]))
elif choix == '7':
matrix = transpose_matrix(matrix)
else:
print('invalid choice')
You aren't actually assigning the result of your manipulations, and therefore return the original matrix unchanged. For example:
def transpose_matrix(matrix):
zip(*matrix) # ignore result of computation
return matrix # return argument unchanged
Instead, try:
def transpose_matrix(matrix):
matrix = list(map(list, zip(*matrix))) # assign result
return matrix # return transposed matrix
or simply:
def transpose_matrix(matrix):
return list(map(list, zip(*matrix)))
Bear in mind that you will need to assign the return from the function in the calling function, too:
matrix = transpose_matrix(matrix)
In-place modification
Alternatively, you could transpose in-place and implicitly return None:
def transpose_matrix(matrix):
matrix[:] = list(map(list, zip(*matrix)))
This way you don't have to assign back to matrix when you call the function.
Examples
Examples of the functions in action:
>>> def transpose_matrix(matrix):
return list(map(list, zip(*matrix)))
>>> transpose_matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
>>> def in_place_transpose(matrix):
matrix[:] = list(map(list, zip(*matrix)))
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> in_place_transpose(m)
>>> m
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
zip behaviour
It is important to note that zip will truncate its output to the shortest argument iterable, e.g.:
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> c = [7, 8]
>>> d = [9]
>>> e = []
>>> for l in (b, c, d, e):
print(list(zip(a, l)))
[(1, 4), (2, 5), (3, 6)]
[(1, 7), (2, 8)]
[(1, 9)]
[]
Therefore if any of the rows of your matrix are empty lists, your output will be an empty list. You can use zip_longest from itertools to insert dummy fillvalues (None by default) instead:
>>> from itertools import zip_longest
>>> list(zip_longest([1, 2, 3], [4, 5]))
[(1, 4), (2, 5), (3, None)]
>>> m = [[1, 2, 3], [4, 5, 6], []]
>>> list(zip_longest(*m, fillvalue=0))
[(1, 4, 0), (2, 5, 0), (3, 6, 0)]
You could implement this as:
def transpose_matrix(matrix):
return list(map(list, zip_longest(*matrix, fillvalue=0)))
with from itertools import zip_longest at the top of your script.
There are some problems with the solutions you tried:
def transpose_matrix(matrix):
zip(*matrix)
return matrix
The result from zip(…) is thrown away, and you return the original matrix instead. Write return zip(*matrix).
def transpose_matrix(matrix):
map(list, zip(*matrix))
return matrix
Same as above, the result from map(…) is thrown away. Write return map(list, zip(*matrix)) instead.
def transpose_matrix(matrix):
print(list(zip(*m)))
The argument is named matrix, but you are working on m. So either rename the parameter m, or change the zipped value to *matrix.
Examples:
>>> m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list(zip(*m))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
>>> list(map(list, zip(*m)))
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Was just wondering what's the most efficient way of generating all the circular shifts of a list in Python. In either direction. For example, given a list [1, 2, 3, 4], I want to generate either:
[[1, 2, 3, 4],
[4, 1, 2, 3],
[3, 4, 1, 2],
[2, 3, 4, 1]]
where the next permutation is generated by moving the last element to the front, or:
[[1, 2, 3, 4],
[2, 3, 4, 1],
[3, 4, 1, 2],
[4, 1, 2, 3]]
where the next permutation is generated by moving the first element to the back.
The second case is slightly more interesting to me because it results in a reduced Latin square (the first case also gives a Latin square, just not reduced), which is what I'm trying to use to do experimental block design. It actually isn't that different from the first case since they're just re-orderings of each other, but order does still matter.
The current implementation I have for the first case is:
def gen_latin_square(mylist):
tmplist = mylist[:]
latin_square = []
for i in range(len(mylist)):
latin_square.append(tmplist[:])
tmplist = [tmplist.pop()] + tmplist
return latin_square
For the second case its:
def gen_latin_square(mylist):
tmplist = mylist[:]
latin_square = []
for i in range(len(mylist)):
latin_square.append(tmplist[:])
tmplist = tmplist[1:] + [tmplist[0]]
return latin_square
The first case seems like it should be reasonably efficient to me, since it uses pop(), but you can't do that in the second case, so I'd like to hear ideas about how to do this more efficiently. Maybe there's something in itertools that will help? Or maybe a double-ended queue for the second case?
You can use collections.deque:
from collections import deque
g = deque([1, 2, 3, 4])
for i in range(len(g)):
print list(g) #or do anything with permutation
g.rotate(1) #for right rotation
#or g.rotate(-1) for left rotation
It prints:
[1, 2, 3, 4]
[4, 1, 2, 3]
[3, 4, 1, 2]
[2, 3, 4, 1]
To change it for left rotation just replace g.rotate(1) with g.rotate(-1).
For the first part, the most concise way probably is
a = [1, 2, 3, 4]
n = len(a)
[[a[i - j] for i in range(n)] for j in range(n)]
# [[1, 2, 3, 4], [4, 1, 2, 3], [3, 4, 1, 2], [2, 3, 4, 1]]
and for the second part
[[a[i - j] for i in range(n)] for j in range(n, 0, -1)]
# [[1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]]
These should also be much more efficient than your code, though I did not do any timings.
variation on slicing "conservation law" a = a[:i] + a[i:]
ns = list(range(5))
ns
Out[34]: [0, 1, 2, 3, 4]
[ns[i:] + ns[:i] for i in range(len(ns))]
Out[36]:
[[0, 1, 2, 3, 4],
[1, 2, 3, 4, 0],
[2, 3, 4, 0, 1],
[3, 4, 0, 1, 2],
[4, 0, 1, 2, 3]]
[ns[-i:] + ns[:-i] for i in range(len(ns))]
Out[38]:
[[0, 1, 2, 3, 4],
[4, 0, 1, 2, 3],
[3, 4, 0, 1, 2],
[2, 3, 4, 0, 1],
[1, 2, 3, 4, 0]]
more_itertools is a third-party library that offers a tool for cyclic permutations:
import more_itertools as mit
mit.circular_shifts(range(1, 5))
# [(1, 2, 3, 4), (2, 3, 4, 1), (3, 4, 1, 2), (4, 1, 2, 3)]
See also Wikipedia:
A circular shift is a special kind of cyclic permutation, which in turn is a special kind of permutation.
The answer by #Bruno Lenzi does not seem to work:
In [10]: from itertools import cycle
In [11]: x = cycle('ABCD')
In [12]: print [[x.next() for _ in range(4)] for _ in range(4)]
[['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D'], ['A', 'B', 'C', 'D']]
I give a correct version below, however the solution by #f5r5e5d is faster.
In [45]: def use_cycle(a):
x=cycle(a)
for _ in a:
x.next()
print [x.next() for _ in a]
....:
In [46]: use_cycle([1,2,3,4])
[2, 3, 4, 1]
[3, 4, 1, 2]
[4, 1, 2, 3]
[1, 2, 3, 4]
In [50]: def use_slice(a):
print [ a[n:] + a[:n] for n in range(len(a)) ]
....:
In [51]: use_slice([1,2,3,4])
[[1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 1, 2], [4, 1, 2, 3]]
In [54]: timeit.timeit('use_cycle([1,2,3,4])','from __main__ import use_cycle',number=100000)
Out[54]: 0.4884989261627197
In [55]: timeit.timeit('use_slice([1,2,3,4])','from __main__ import use_slice',number=100000)
Out[55]: 0.3103291988372803
In [58]: timeit.timeit('use_cycle([1,2,3,4]*100)','from __main__ import use_cycle',number=100)
Out[58]: 2.4427831172943115
In [59]: timeit.timeit('use_slice([1,2,3,4]*100)','from __main__ import use_slice',number=100)
Out[59]: 0.12029695510864258
I removed the print statement in use_cycle and use_slice for timing purposes.
Using itertools to avoid indexing:
x = itertools.cycle(a)
[[x.next() for i in a] for j in a]
This will be my solution.
#given list
a = [1,2,3,4]
#looping through list
for i in xrange(len(a)):
#inserting last element at the starting
a.insert(0,a[len(a)-1])
#removing the last element
a = a[:len(a)-1]
#printing if you want to
print a
This will output the following:
[4, 1, 2, 3]
[3, 4, 1, 2]
[2, 3, 4, 1]
[1, 2, 3, 4]
You can also use pop instead of using list slicing but the problem with pop is that it will return something.
Also the above code will work for any length of list. I have not checked for performance of the code. I am assuming that it will work better.
You should have a look at Python docs for getting a good understanding of List slicing.