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
Related
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)}
I have a 3 lists :
a = [10, 9, 8, 7, 6]
b = [8, 7, 6, 5, 4, 3]
c = [6, 5, 4, 3, 2]
I need to get all the permutations obtained with itertools.product(), BUT only if the values are decreasing:
[10, 8, 6] # is good
[6, 8, 4] # is not good, since 8 > 6
Is there a simple way to do it or should I go with list comprehension and conditions ?
You could do this with a list comprehension by looping over theitertools.product iterator and extracting only those returned items that are sorted in reverse:
[item for item in product(a,b,c) if sorted(item, reverse = True) == list(item)]
Example:
from itertools import product
a = [10,9,8,7,6]
b = [8, 7, 6, 5, 4, 3]
c = [6, 5, 4, 3, 2]
[item for item in product(a,b,c) if sorted(item, reverse = True) == list(item)]
# [(10, 8, 6), (10, 8, 5), (10, 8, 4), (10, 8, 3), (10, 8, 2) ...continues
You can refer following code which does not have list comprehensions:
from itertools import product
a = [10, 9, 8, 7, 6]
b = [8, 7, 6, 5, 4, 3]
c = [6, 5, 4, 3, 2]
for result in product(a,b,c):
if sorted(result, reverse = True) == list(result):
print result
This is a simple one line solution
>>> mylist = [10, 9, 8, 7, 6]
>>> all(earlier >= later for earlier, later in zip(mylist, mylist[1:]))
True
>>> mylist = [10, 9, 7, 8, 6]
>>> all(earlier >= later for earlier, later in zip(mylist, mylist[1:]))
False
I found this here:
Determine if a list is in descending order
If you don't want to use list comprehensions for some reason:
def decreasing(l):
return all(a >= b for a, b in zip(l[:-1], l[1:]))
filter(decreasing, product(a, b, c))
I have a list with several sublists (unknown number), e.g.
[[1, 2, 3], [4, 5, 6]]
I want to print the content of sublists, without brackets, in parentheses, separated with commas and gaps like this
(1, 2, 3)
(4, 5, 6)
I have tried using
for i in range(0, len(l)):
print('(',*l[i],')')
but it does not work. It just gives me:
( 1 2 3 )
( 4 5 6 )
which is not what I want
Any idea how I can get the result I need?
This will work:
for i in l:
print('('+",".join(map(str, i))+')')
a=[[1, 2, 3],[4, 5, 6]]
for l in a:
print(tuple(l))
Here are couple of ways to do it:
>>> l = [[1, 2, 3], [4, 5, 6]]
>>> print(*map(tuple, l), sep='\n')
(1, 2, 3)
(4, 5, 6)
>>>
>>> for sub_l in l:
print(tuple(sub_l))
(1, 2, 3)
(4, 5, 6)
So I have 2 lists, say list a and list b where
a = [9, 8, 7, 6]
b = [1, 2, 3, 4]
How would I go about subtracting the contents of b from a?
You can use the map function and it's feature to support more than one iterable (the following assumes Python2):
>>> a = [9, 8, 7, 6]
>>> b = [1, 2, 3, 4]
>>> map(lambda x,y: x-y, a, b)
[8, 6, 4, 2]
map applies the first argument (which has to be a function) on all elements of the following arguments. For example:
>>> from math import sqrt
>>> map(sqrt, [1,2,9])
[1.0, 1.4142135623730951, 3.0]
If you use more than two arguments, the function in the first parameter must take more parameters, because it is called with elements from each list:
>>> from math import pow
>>> map(pow, [2,3,4], [2,3,4])
[4.0, 27.0, 256.0]
The result is 2^2, 3^3 and 4^4.
The lambda in my example is just a shorter way to define the subtraction function, the following code would do the same:
def sub(x,y):
return x-y
map(sub, a, b)
You can zip the two lists and subtract the subelements to create a new list:
zip(b,a) -> [(1, 9), (2, 8), (3, 7), (4, 6)]
a = [9, 8, 7, 6]
b = [1, 2, 3, 4]
print([y-x for x,y in zip(b,a)])
[8, 6, 4, 2]
If you want to change a itself use enumerate subtracting elements at common indexes:
for ind,ele in enumerate(a):
a[ind] -= b[ind]
print(a)
[8, 6, 4, 2]
Or using numpy:
import numpy as np
a = np.array([9, 8, 7, 6])
b = np.array([1, 2, 3, 4])
print(a - b)
[8 6 4 2]
a=[1,2,3,4,5]
b=[9,8,7,6,4]
t=0
h=[]
lenA=len(a)
while lenA != t:
x=a[t]-b[t]
t=t+1
h.append(x)
What is the best way to do this:
>>> replace2([1, 2, 3, 4, 5, 6])
[2, 1, 4, 3, 6, 5]
def replace2inplace(lst):
lst[1::2], lst[::2] = lst[::2], lst[1::2]
This uses slice assignment and slice step sizes to swap every pair in the list around, in-place:
>>> somelst = [1, 2, 3, 4, 5, 6]
>>> replace2inplace(somelst)
>>> somelst
[2, 1, 4, 3, 6, 5]
Otherwise you could use some itertools tricks:
from itertools import izip, chain
def replace2copy(lst):
lst1, lst2 = tee(iter(lst), 2)
return list(chain.from_iterable(izip(lst[1::2], lst[::2])))
which gives:
>>> replace2([1, 2, 3, 4, 5, 6])
[2, 1, 4, 3, 6, 5]
with the list() call optional; if you only need to loop over the result the generator is enough:
from itertools import izip, chain, islice, tee
def replace2gen(lst):
lst1, lst2 = tee(iter(lst))
return chain.from_iterable(izip(islice(lst1, 1, None, 2), islice(lst2, None, None, 2)))
for i in replace2gen([1, 2, 3, 4, 5, 6]):
print i
where replace2gen() can take arbitrary iterators too.
Out-of-place version:
def replace2(lst):
return [x for pair in zip(lst[1::2], lst[::2]) for x in pair]
My choice:
x = range(1,7)
res = [e for e in itertools.chain(*zip(x[1::2],x[0::2]))]
>>> a = [1, 2, 3, 4, 5, 6]
>>> sum([[x+1,x] for x in a if x&1 == True],[])
[2, 1, 4, 3, 6, 5]
EDIT: Some further explanation was requested:
The code steps through each element in the list a and, if the element is odd (x&1 == True) it puts that element and the next element into a list in reverse order ([x+1,x]).
With out the sum(...,[]) function we would have
[[2, 1], [4, 3], [6, 5]]
The sum(...,[]) function removes the internal square brackets giving
[2, 1, 4, 3, 6, 5]
This can be done more generally by using the index of the list rather than its value:
>>> a = [1, 2, 3, 4, 5, 6]
>>> sum([[a[x],a[x-1]] for x in range(len(a)) if x&1 == True],[])
[2, 1, 4, 3, 6, 5]
However, this will remove the last element of the list if its length is not even.