Given a list:
mylist = [1,6,4,9,2]
I would like to return all pairs of consecutive items within a window.
For example, if I want pairs of 3 consecutive items, I could do:
items=3
for x in range(0,len(mylist)-items+1):
print(mylist[x:x+items])
Which outputs:
[1, 6, 4]
[6, 4, 9]
[4, 9, 2]
This assumes the window size is also 3, so it's only scanning 3 indexes at a time.
If I instead want to return all pairs of 3 consecutive items in a window of 4, I would want:
[1, 6, 4]
[1, 6, 9]
[1, 4, 9]
[6, 4, 9]
[6, 4, 2]
[6, 9, 2]
[4, 9, 2]
Is there a simple method to produce these pairs?
Edit to add to Alex's answer below:
I ended up using combinations to identify the indexes, then only selecting the indexes starting with zero, like this:
from itertools import combinations
def colocate(mylist,pairs=4,window=6):
x = list(combinations(range(window),pairs))
y = [z for z in x if z[0]==0]
for item in y:
print(item)
"Combination" is a concept in math related to your question. It does not care about "window of 4" though.
from itertools import combinations
l = [1,6,4,9,2]
for combination in combinations(l, 3):
print(combination)
(1, 6, 4)
(1, 6, 9)
(1, 6, 2)
(1, 4, 9)
(1, 4, 2)
(1, 9, 2)
(6, 4, 9)
(6, 4, 2)
(6, 9, 2)
(4, 9, 2)
I'm curious why do you want to have a window of 4.
Maybe there is a better way to solve your task at hand?
One fairly easy way to do it is to think about it in terms of the index rather than the list items itself. Start with:
import itertools
list(itertools.combinations(range(len(mylist)), 3)
This gets you all the possible index triple combinations in a list with the length of your list. Now you want to filter them to exclude any where the last index is 4 or more away from the first:
list(filter(lambda seq: (seq[-1] - seq[0]) <= 4, itertools.combinations(l, 3)))
This gets you the indeces you want. So now you can get the triples you need based on the indeces:
[[mylist[i] for i in seq] for seq in filter(lambda seq: (seq[-1] - seq[0]) < 4, itertools.combinations(l, 3))]
which produces:
[[1, 6, 4], [1, 6, 9], [1, 4, 9], [6, 4, 9], [6, 4, 2], [6, 9, 2], [4, 9, 2]]
This gets pretty close. There will be some duplicates produced, but that's what set(...) is for at the end... should give you some ideas anyway.
from itertools import combinations, islice, chain
# from itertools examples
def window(seq, n=2):
"Returns a sliding window (of width n) over data from the iterable"
" s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ... "
it = iter(seq)
result = tuple(islice(it, n))
if len(result) == n:
yield result
for elem in it:
result = result[1:] + (elem,)
yield result
mylist = [1,6,4,9,2]
set(chain.from_iterable(combinations(w, 3) for w in window(mylist, 4)))
{(1, 4, 9), (1, 6, 4), (1, 6, 9), (4, 9, 2), (6, 4, 2), (6, 4, 9), (6, 9, 2)}
Related
How to get the transpose of this matrix..Any easier ,algorithmic way to do this...
1st question:
Input a=[[1,2,3],[4,5,6],[7,8,9]]
Expected output a=[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
2nd Question:
Zip gives me the following output said below,how can i zip when i dont know how many elements are there in the array,in this case i know 3 elements a[0],a[1],a[2] but how can i zip a[n] elements
>>> zip(a[0],a[1],a[2])
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
Use zip(*a):
>>> zip(*a)
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
How it works: zip(*a) is equal to zip(a[0], a[1], a[2]).
question answers:
>>> import numpy as np
>>> first_answer = np.transpose(a)
>>> second_answer = [list(i) for i in zip(*a)]
thanks to afg for helping out
Solution is to use tuple() function.
Here is an example how to do that in your case :
a = [[1,2,3],[4,5,6],[7,8,9]]
output = tuple(zip(*a))
print(output)
You can use numpy.transpose
numpy.transpose
>>> import numpy
>>> a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> numpy.transpose(a)
array([[1, 4, 7],
[2, 5, 8],
[3, 6, 9]])
You can use list(zip(*a)).
By using *a, your list of lists can have any number of entries.
Without zip
def transpose(A):
res = []
for col in range(len(A[0])):
tmp = []
for row in range(len(A)):
tmp.append(A[row][col])
res.append(tmp)
return res
Using zip
def transpose(A):
return map(list, zip(*A))
Try this replacing appropriate variable
import numpy as np
data = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11))
data_transpose = np.transpose(data) # replace with your code
print(data_transpose)
I have no clue where to begin with this, I am new to coding so I am trying my best but I am stuck. I am asking for where to begin or some psuedocode, not for you to write it for me.
Say you have a variable n which is a list of integers which you need to split up into a sublist of x length.
Next suppose that k is len(n)/len_of_sublist
The values from numbers at indexes 0, k, 2k, ... will be placed in the first sub-list.
The values from numbers at indexes 1, k + 1, 2k + 1, ... will be placed in the second sub-list.
The values from numbers at indexes 2, k + 2, 2k + 2, ... will be placed in the third sub-list.
to create list of sublist (l2) from original list (l1), i is the length of sublist :
>>> l1 = [1,2,3,4,5,6,7,8,9,10]
>>> i=2
>>> l2= [l1[n:n+i] for n in range(0, len(l1), i)]
>>> l2
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
With an other c]value of i :
>>> i=3
>>> l2= [l1[n:n+i] for n in range(0, len(l1), i)]
>>> l2
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
>>> n=[1,2,3,4,5,6,7,8,9,10,11,12]
>>> k=4
>>> zip(*[n[i:i+l] for i in range(0,len(n),l)])
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
This will give you elements at 0,k,2k.. / 1,k+1,2k+1.. / 2,k+2,2k+2.. where k=len(n)/x. So you get k sublists of length x.
Note: This will only work if len(n)=k*x perfectly. If not the results would be as below...
>>> k=5
>>> zip(*[n[i:i+k] for i in range(0,len(n),k)])
[(1, 6, 11), (2, 7, 12)]
I have a list of 4 items like this:
a, b, c, d = [1, 2, 3, 4]
I'm reordering the list, flipping each pair:
[b, a, d, c]
Is there a way to do this in one expression? I've tried using list comprehension and unpacking, but can't seem to get it right.
I have [1, 2, 3, 4]. I'm trying to get [2, 1, 4, 3].
More generically, if you're looking to flip pairs of numbers in a list:
>>> L = [1, 2, 3, 4, 5, 6]
>>> from itertools import chain
>>> list(chain.from_iterable(zip(L[1::2], L[::2])))
[2, 1, 4, 3, 6, 5]
Look at this:
>>> lst = [1, 2, 3, 4]
>>> [y for x in zip(*[iter(lst)]*2) for y in x[::-1]]
[2, 1, 4, 3]
>>>
>>> lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [y for x in zip(*[iter(lst)]*2) for y in x[::-1]]
[2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
>>>
If this is only about 4 member lists - this would suffice:
list = [1, 2, 3, 4]
reordered_list = [list[1], list[0], list[3],list[2]]
Because absolutely nobody has given an answer that works on generic iterables,
from itertools import chain
items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
zip(*[iter(items)]*2)
#>>> <zip object at 0x7fd673afd050>
[itms for itms in zip(*[iter(items)]*2)]
#>>> [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
So zip(*[iter(x)]*2) means ix = iter(x); zip(ix, ix) which pairs each element.
Then you can reverse:
[(y, x) for (x, y) in zip(*[iter(items)]*2)]
#>>> [(2, 1), (4, 3), (6, 5), (8, 7), (10, 9)]
Putting it all together and flattening:
[itm for (x, y) in zip(*[iter(items)]*2) for itm in (y, x)]
#>>> [2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
It's generic and short!
If you want something faster at the expense of genericism, you'll be hard pressed to better this:
new = list(items)
new[::2], new[1::2] = new[1::2], new[::2]
new
#>>> [2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
Note that this still works on arbitrary iterables, but there are fewer layers of abstraction; you can't bump up the size of the flipped sub-lists as easily and can't output iterables, etc.
Do you mean this:
>>> a, b, c, d = [1, 2, 3, 4]
>>> b, a, d, c = a, b, c, d
>>> a
2
>>> b
1
>>> c
4
>>> d
3
?
Try this list comprenhension solution:
a = [1,2,3,4,5,6] # Any list with even number of elements
b = [a[e+1] if (e%2 == 0) else a[e-1] for e in range(len(a))]
This just works if the list a have an even number of elements.
In [1]: l = [1, 2, 3, 4]
In [2]: list(chain(*map(reversed, zip(l[::2], l[1::2]))))
Out[2]: [2, 1, 4, 3]
Am I missing something? Reorder given_list with a loop:
rez = []
for i in range(len(given_list)-1, -1, -1):
rez.append(given_list[i])
return rez
I have a list [2,3,4]. How do I find all possible sequence of elements in the list?
So the output should be:
[2,3,4]
[2,4,3]
[3,2,4]
[3,4,2]
[4,2,3]
[4,3,2]
You can do this easily using itertools.permutations():
>>> from itertools import permutations
>>> list(permutations([2, 3, 4]))
[(2, 3, 4), (2, 4, 3), (3, 2, 4), (3, 4, 2), (4, 2, 3), (4, 3, 2)]
And if for some reason you need lists instead of tuples:
>>> map(list, permutations([2, 3, 4]))
[[2, 3, 4], [2, 4, 3], [3, 2, 4], [3, 4, 2], [4, 2, 3], [4, 3, 2]]
You are looking for permutations, something like this should work:
import itertools
itertools.permutations([2,3,4])
a start of a great lottery program except data would be formated as such
ist(permutations([2, 3, 4],[7,2,5],[8,1,4,9]))
the problem is that the first group is used to create numbers in first column only
the secound is for 2 column and 3rd is for 3rd
the output will be a set of 3 numbers just that the permutation is different
Just so you know:
def unique_perms(elems):
"""returns non-duplicate permutations
if duplicate elements exist in `elems`
"""
from itertools import permutations
return list(set(permutations(elems)))
But if you're doing something like this:
print len(unique_perms(elems))
Then try this:
def fac(n):
"""n!"""
if n == 1: return n
return n * fac(n -1)
def unique_perm_count(elems)
n = len(elems)
return fac(2 * n) / fac(n) ** 2
In Python, it is easy to break an n-long list into k-size chunks if n is a multiple of k (IOW, n % k == 0). Here's my favorite approach (straight from the docs):
>>> k = 3
>>> n = 5 * k
>>> x = range(k * 5)
>>> zip(*[iter(x)] * k)
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)]
(The trick is that [iter(x)] * k produces a list of k references to the same iterator, as returned by iter(x). Then zip generates each chunk by calling each of the k copies of the iterator exactly once. The * before [iter(x)] * k is necessary because zip expects to receive its arguments as "separate" iterators, rather than a list of them.)
The main shortcoming I see with this idiom is that, when n is not a multiple of k (IOW, n % k > 0), the left over entries are just left out; e.g.:
>>> zip(*[iter(x)] * (k + 1))
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)]
There's an alternative idiom that is slightly longer to type, produces the same result as the one above when n % k == 0, and has a more acceptable behavior when n % k > 0:
>>> map(None, *[iter(x)] * k)
[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)]
>>> map(None, *[iter(x)] * (k + 1))
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14, None)]
At least, here the left over entries are retained, but the last chunk gets padded with None. If one just wants a different value for the padding, then itertools.izip_longest solves the problem.
But suppose the desired solution is one in which the last chunk is left unpadded, i.e.
[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14)]
Is there a simple way to modify the map(None, *[iter(x)]*k) idiom to produce this result?
(Granted, it is not difficult to solve this problem by writing a function (see, for example, the many fine replies to How do you split a list into evenly sized chunks? or What is the most "pythonic" way to iterate over a list in chunks?). Therefore, a more accurate title for this question would be "How to salvage the map(None, *[iter(x)]*k) idiom?", but I think it would baffle a lot of readers.)
I was struck by how easy it is to break a list into even-sized chunks, and how difficult (in comparison!) it is to get rid of the unwanted padding, even though the two problems seem of comparable complexity.
[x[i:i+k] for i in range(0,n,k)]
sentinal = object()
split = (
(v for v in r if v is not sentinal) for r in
izip_longest(*[iter(x)]*n, fillvalue=sentinal))
Of course, the better idiom is to call a function as that'll be more readable then anything that'll do the same thing.
from IPython's source:
def chop(seq,size):
"""Chop a sequence into chunks of the given size."""
chunk = lambda i: seq[i:i+size]
return map(chunk,xrange(0,len(seq),size))
The last list returned will have fewer than chunk elements if the sequence isn't evenly divisible, basically it gets the short end of the stick but without complaining.
>>> chop(range(12),3)
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
>>> chop(range(12),4)
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
>>> chop(range(12),5)
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11]]
>>> chop(range(12),6)
[[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]]
What about this? It's a different idiom, but produces your desired result:
[x[i:i+k] for i in range(0,len(x),k)] #=> [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14]]
[x[i:i+k] for i in range(0,len(x),k)] #=> [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14]]
Or if you really need tuples, use tuple(x[i:i+k]) instead of just x[i:i+k].