I have two lists (X and Y). I want to first scale the first element of X with all the elements of Y before moving to the second element of X which is then again scaled by all the elements of Y. How can I do this? Ideally, I would also like to append it to different lists (L) when a new element of X is started, but I am not sure if that is possible.
Y = [2, 3, 4, 5]
X = [1, 2, 3, 4]
L = []
for i in range(len(X)):
for j in range(len(Y)):
X_scale = X[i] * Y[j]
L.append(X_scale)
Preferred outcome:
# First element in X
X_scale = [2, 2, 3, 4]
X_scale = [3, 2, 3, 4]
X_scale = [4, 2, 3, 4]
X_scale = [5, 2, 3, 4]
# Second element in X
X_scale = [1, 4, 3, 4]
X_scale = [1, 6, 3, 4]
#etc
This seems to follow your pattern:
Y = [2, 3, 4, 5]
X = [1, 2, 3, 4]
L = []
for i,x in enumerate(X):
for y in Y:
X_scale = X.copy()
X_scale[i] = x * y
L.append(X_scale)
for row in L:
print(row)
Output:
[2, 2, 3, 4]
[3, 2, 3, 4]
[4, 2, 3, 4]
[5, 2, 3, 4]
[1, 4, 3, 4]
[1, 6, 3, 4]
[1, 8, 3, 4]
[1, 10, 3, 4]
[1, 2, 6, 4]
[1, 2, 9, 4]
[1, 2, 12, 4]
[1, 2, 15, 4]
[1, 2, 3, 8]
[1, 2, 3, 12]
[1, 2, 3, 16]
[1, 2, 3, 20]
Per OP's comment to group the indices:
Y = [2, 3, 4, 5]
X = [1, 2, 3, 4]
L = []
for i,x in enumerate(X):
L2 = []
for y in Y:
X_scale = X.copy()
X_scale[i] = x * y
L2.append(X_scale)
L.append(L2)
for row in L:
print(row)
Output:
[[2, 2, 3, 4], [3, 2, 3, 4], [4, 2, 3, 4], [5, 2, 3, 4]]
[[1, 4, 3, 4], [1, 6, 3, 4], [1, 8, 3, 4], [1, 10, 3, 4]]
[[1, 2, 6, 4], [1, 2, 9, 4], [1, 2, 12, 4], [1, 2, 15, 4]]
[[1, 2, 3, 8], [1, 2, 3, 12], [1, 2, 3, 16], [1, 2, 3, 20]]
First you can simply you loops by accessing the items directly, without an index. Then you can transform the inner loop into a comprehension list to make it more compact:
Y = [2, 3, 4, 5]
X = [1, 2, 3, 4]
L = []
for x_item in X:
L += [x_item * y_item for y_item in Y]
Related
I have a list [1, 2, 3, 4, ..., n]. In a one-liner list comprehension, how can I print the progression [1], [1, 2], [1, 2, 3], [1, 2, 3, 4], ..., [1, 2, 3, 4, ..., n-1], where n represents an arbitrary natural number?
Now if you want this principle to operate on any starting list (not necessarily [1,2,...]), you can do this:
rawlist=['a','b','c','d']
newlist=[rawlist[:i] for i in range(1,len(rawlist)+1)]
Try this:
n = 10
res = [list(range(1,i)) for i in range(2,n+1)]
print(res)
Output:
[
[1], # range(1, 2)
[1, 2], # range(1, 3)
[1, 2, 3],
[1, 2, 3, 4],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6, 7],
[1, 2, 3, 4, 5, 6, 7, 8],
[1, 2, 3, 4, 5, 6, 7, 8, 9] # range(1, 10)
]
How about a for loop in a for loop?
n = 10
print([[x for x in range(1,i+1)] for i in range(1,n+1)])
This prints an array of the numbers 1 to i for each value of i in the range 1 to n.
This should give you every list from [1] to [1,...n-1]
[print([x for x in range(1, y+1)]) for y in range(1, n)]
Starting with our [1, ..., n] list, where n in this case is 5:
>>> a_list = list(range(1, 6))
>>> a_list
[1, 2, 3, 4, 5]
we can just iterate over the list and create another list for each number, with the last one ending in n-1:
>>> print(*[list(range(1, x)) for x in a_list[1:]], sep=", ")
[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]
Or, doing it based on n directly rather than a_list:
>>> n = 5
>>> print(*[list(range(1, x)) for x in range(2, n+1)], sep=", ")
[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]
Note that using a list comprehension is not necessary; you can replace the outer [] in both examples with () (i.e. a parenthesized generator expression rather than a list comprehension) and it will print exactly the same thing.
Hi I've been trying to figure out why in this code 'permutations.append(lst)' is not only appending twice, but also deleted the first term in the 'permutations'.
def permute(lst):
permutations = []
permutations.append(lst)
flag = True
while flag:
k = len(lst) - 2
while k>=0:
if lst[k] < lst[k+1]:
break
k -= 1
else:
flag = False
break
l = len(lst) - 1
while l>k:
if lst[k] < lst[l]:
break
l-=1
lst[k], lst[l] = lst[l], lst[k]
lst = lst[:k+1] + lst[len(lst)-1: k :-1]
print('a')
permutations.append(lst)
print(lst, 'b')
return permutations
print(permute([2,3,4,5])
I placed the print commands to check if for some reason the block is running twice but it doesnt. Instead of the final permutations being nested lists of all the permutations of [2,3,4,5] in order, it gives this:
[[2, 3, 5, 4], [2, 4, 5, 3], [2, 4, 5, 3], [2, 5, 4, 3], [2, 5, 4, 3], [3, 5, 4, 2], [3, 2, 5, 4], [3, 4, 5, 2], [3, 4, 5, 2], [3, 5, 4, 2], [3, 5, 4, 2], [4, 5, 3, 2], [4, 2, 5, 3], [4, 3, 5, 2], [4, 3, 5, 2], [4, 5, 3, 2], [4, 5, 3, 2], [5, 4, 3, 2], [5, 2, 4, 3], [5, 3, 4, 2], [5, 3, 4, 2], [5, 4, 3, 2], [5, 4, 3, 2], [5, 4, 3, 2]]
This is because when you are appending lst to permutations, you're actually appending a reference to an object, rather than just the values of the object. As such, when you then change the values of lst later, permutations also changes.
list.copy() returns just the values of a list, decoupled from the original object. As such, if you replace your permutations.append(lst) lines with permutations.append(lst.copy()), you should get the desired output.
Demonstration of list reference effect vs copied list:
>>> x = [1]
>>> y = []
>>> y.append(x) # Directly append x to y
>>> y
[[1]]
>>> x[0] = 2
>>> y # Changing x changed y
[[2]]
>>> y = []
>>> y.append(x.copy()) # Append copy of x to y
>>> y
[[2]]
>>> x[0] = 3
>>> y # Changing x had no effect on y
[[2]]
Similiar questions to this one have been asked before, but none exactly like it an and I'm kind of lost.
If I have 2 sets of lists (or a lists of lists)
listOLists = [[1,2,3],[1,3,2]]
listOLists2 = [[4,5,6],[4,6,5]]
And I want 'merge' the two lists to make
mergedLists = [[1,2,3,4,5,6],[1,3,2,4,5,6],[1,2,3,4,6,5],[1,3,2,4,6,5]]
How would I do this?
list1s=[[1,2,3],[3,2,1],[2,2,2]]
list2s=[[3,3,3],[4,4,4],[5,5,5]]
for indis1 in list1s:
for indis2 in list2s:
print(indis1 + indis2)
try and;
[1, 2, 3, 3, 3, 3]
[1, 2, 3, 4, 4, 4]
[1, 2, 3, 5, 5, 5]
[3, 2, 1, 3, 3, 3]
[3, 2, 1, 4, 4, 4]
[3, 2, 1, 5, 5, 5]
[2, 2, 2, 3, 3, 3]
[2, 2, 2, 4, 4, 4]
[2, 2, 2, 5, 5, 5]
You may use generator to simplify your code, like this:
a = [[1, 2, 3], [1, 3, 2], [2, 1, 3]]
b = [[4, 5, 6], [4, 6, 5], [5, 4, 6]]
c = [i + j for i in a for j in b]
print c
Output:
[[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 6, 5], [1, 2, 3, 5, 4, 6], [1, 3, 2, 4, 5, 6], [1, 3, 2, 4, 6, 5], [1, 3, 2, 5, 4, 6], [2, 1, 3, 4, 5, 6], [2, 1, 3, 4, 6, 5], [2, 1, 3, 5, 4, 6]]
list1 = [[1,2,3],[1,3,2]]
list2 = [[4,5,6],[4,6,5]]
mergedLists = []
for list1_inner in list1:
for list2_inner in list2:
mergedLists.append(list1_inner + list2_inner)
print(mergedLists)
A comparison of methods:
import itertools
import random
l1 = [[random.randint(1,100) for _ in range(100)]for _ in range(100)]
l2 = [[random.randint(1,100) for _ in range(100)]for _ in range(100)]
With itertools:
def itert(l1, l2):
[list(itertools.chain(*x)) for x in itertools.product(l1, l2)]
With for loops:
def forloops(list1, list2):
mergedLists = []
for list1_inner in list1:
for list2_inner in list2:
mergedLists.append(list1_inner + list2_inner)
With a simple Comprehension:
def comp(l1, l2):
[i + j for i in l1 for j in l2]
Speed
%time itert(l1, l2)
Wall time: 99.8 ms
%time comp(l1, l2)
Wall time: 31.3 ms
%time forloops(l1, l2)
Wall time: 46.9 ms
I want to extract the i indices of a vector uniformly t times. For instance, if I have a vector x = [1,2,3,4,5,6,7], i = 3 and t = 5, my indices in each time must be:
t = 1; [1,2,3]
t = 2; [4,5,6]
t = 3; [7,1,2]
t = 4; [3,4,5]
t = 5; [6,7,1]
Would it be possible to do it in Python with range()?
You can use itertools.islice on itertools.cycle. Make a cycle object from the iterable, and slice the object using your window size i:
from itertools import cycle
from itertools import islice
l = [1,2,3,4,5,6,7]
t = 5; i = 3
c = cycle(l)
r = [list(islice(c, i)) for _ in range(t)] # range appears here
# [[1, 2, 3], [4, 5, 6], [7, 1, 2], [3, 4, 5], [6, 7, 1]]
You can apply this for different non-negative values of i, and even when i is greater than the length of your list:
i = 10
r = [list(islice(c, i)) for _ in range(t)]
print(r)
# [[1, 2, 3, 4, 5, 6, 7, 1, 2, 3], [4, 5, 6, 7, 1, 2, 3, 4, 5, 6], [7, 1, 2, 3, 4, 5, 6, 7, 1, 2], [3, 4, 5, 6, 7, 1, 2, 3, 4, 5], [6, 7, 1, 2, 3, 4, 5, 6, 7, 1]]
Try this:
x = [1,2,3,4,5,6,7]
xc = len(x)
i = 3
for t in range(5):
y = [x[(i*t + j) % xc] for j in range(i)]
print(y)
This produces:
[1, 2, 3]
[4, 5, 6]
[7, 1, 2]
[3, 4, 5]
[6, 7, 1]
I'm struggling to understand how to combine elements from a list.
I have:
a = [[1, 2], [3, 4, 5], [6], [7, 8, 9, 10]]
I want to create triplets by taking elements from each list members
but always including the first element. This piece of code does half the
job:
r=[[]]
for x in a[0:3]:
t = []
for y in x:
for i in r:
t.append(i+[y])
r = t
r
[[1, 3, 6], [2, 3, 6], [1, 4, 6], [2, 4, 6], [1, 5, 6], [2, 5, 6]]
but I also want:
[[1,6,7], [1,6,8], [1,6,9] etc.]
Could someone please suggest a good method to do that?
Using itertools:
import itertools
a = [[1, 2], [3, 4, 5], [6], [7, 8, 9, 10]]
for xss in itertools.combinations(a, 3): # pick 3 lists.
# xss => ([1, 2], [3, 4, 5], [6])
# ([1, 2], [3, 4, 5], [7, 8, 9, 10])
# ...
indexed = [enumerate(x) for x in xss]
# indexed => [[(0, 1), (1, 2)], [(0, 3), (1, 4), (2, 5)], [(0, 6)]]
# ^^^^^^^^^^^^^^^^ list(enumerate([1, 2]))
for xs in itertools.product(*indexed):
# xs => ((0, 1), (0, 3), (0, 6))
# ((0, 1), (0, 3), (0, 7))
# ((0, 1), (0, 6), (0, 7))
# ...
if all(i > 0 for i, x in xs): # exclude no first item is selected.
continue
print [x for i, x in xs]
UPDATE response to the comment.
import itertools
a = [[1, 2], [3, 4, 5], [6], [7, 8, 9, 10]]
for xss in itertools.combinations(a[1:], 2):
xss = (a[0],) + xss
indexed = [enumerate(x) for x in xss]
for xs in itertools.product(*indexed):
if all(i > 0 for i, x in xs):
continue
print [x for i, x in xs]
output:
[1, 3, 6]
[1, 4, 6]
[1, 5, 6]
[2, 3, 6]
[2, 4, 6]
[2, 5, 6]
[1, 3, 7]
[1, 3, 8]
[1, 3, 9]
[1, 3, 10]
[1, 4, 7]
[1, 4, 8]
[1, 4, 9]
[1, 4, 10]
[1, 5, 7]
[1, 5, 8]
[1, 5, 9]
[1, 5, 10]
[2, 3, 7]
[2, 3, 8]
[2, 3, 9]
[2, 3, 10]
[2, 4, 7]
[2, 5, 7]
[1, 6, 7]
[1, 6, 8]
[1, 6, 9]
[1, 6, 10]
[2, 6, 7]
[2, 6, 8]
[2, 6, 9]
[2, 6, 10]