How to replace indexes by values from different list? - python

I have two lists:
test_list1 = [2, 3, 4, 5, 2, 4]
test_list2 = [[1, 5], [4, 2, 3], [0]]
I want to replace the indexes in test_list2 by the values in test_list1 such that the result would be:
[[3, 4], [2, 4, 5], [2]]
I have tried this:
res = [test_list1[idx] for idx in test_list2]
I have notice that my code only works for a list without sublists

A oneliner with list comprehension and map function could look like this:
test_list1 = [2, 3, 4, 5, 2, 4]
test_list2 = [[1, 5], [4, 2, 3], [0]]
output = list(map(lambda x: [test_list1[y] for y in x], test_list2))
print(output)
# [[3, 4], [2, 4, 5], [2]]

You can use a recursive function. This will go through an arbitarily nested list, replacing the values.
def replace(lst, replacements):
for i, val in enumerate(lst):
if isinstance(val, list):
replace(val, replacements)
else:
lst[i] = replacements[val]
test_list1 = [2, 3, 4, 5, 2, 4]
test_list2 = [[1, 5], [4, 2, 3], [0]]
replace(test_list2, test_list1)
print(test_list2)
Gives:
[[3, 4], [2, 4, 5], [2]]

Related

Removing elements from sublists in Python

I have two lists A1 and J1 containing many sublists. From each sublist of A1[0], I want to remove the element specified in J1[0]. I present the current and expected outputs.
A1 = [[[1, 3, 4, 6], [0, 2, 3, 5]], [[1, 3, 4, 6], [1, 3, 4, 6]]]
J1 = [[[1], [2]], [[1], [4]]]
arD = []
for i in range(0,len(A1)):
for j in range(0,len(J1)):
C=set(A1[i][j])-set(J1[i][j])
D=list(C)
arD.append(D)
D=list(arD)
print("D =",D)
The current output is
D = [[3, 4, 6], [0, 3, 5], [3, 4, 6], [1, 3, 6]]
The expected output is
D = [[[3, 4, 6], [0, 3, 5]],[[3, 4, 6],[1, 3, 6]]]
Code:-
A1 = [[[1, 3, 4, 6], [0, 2, 3, 5]], [[1, 3, 4, 6], [1, 3, 4, 6]]]
J1 = [[[1], [2]], [[1], [4]]]
arD=[]
for i in range(0,len(A1)):
tmp=[] #Created a tmp variable list
for j in range(0,len(J1)):
C=set(A1[i][j])-set(J1[i][j])
tmp.append(list(C)) #Appending result in tmp variable
arD.append(tmp) #Storing tmp list as a list of lists in arD.
print("D =",arD)
Output:-
D = [[[3, 4, 6], [0, 3, 5]], [[3, 4, 6], [1, 3, 6]]]
Use list comprehension:
print([[[num for num in subsub_A1 if num not in subsub_J1]
for subsub_A1, subsub_J1 in zip(sub_A1, sub_J1)]
for sub_A1, sub_J1 in zip(A1, J1)])
Output:
[[[3, 4, 6], [0, 3, 5]], [[3, 4, 6], [1, 3, 6]]]
If you have an arbitrary list depth, consider using a recursive function:
def cleanup(A, J):
for l1, l2 in zip(A, J):
if l1 and isinstance(l1[0], list):
cleanup(l1, l2)
else:
s = set(l2)
l1[:] = [x for x in l1 if x not in s]
cleanup(A1, J1) # operation is in place
print(A1)
Output: [[[3, 4, 6], [0, 3, 5]], [[3, 4, 6], [1, 3, 6]]]
Try using remove method if you don't mind corrupting the original data:
from contextlib import suppress
A1 = [[[1, 3, 4, 6], [0, 2, 3, 5]], [[1, 3, 4, 6], [1, 3, 4, 6]]]
J1 = [[[1], [2]], [[1], [4]]]
for A, J in zip(A1, J1):
for a, j in zip(A, J):
for x in j:
with suppress(ValueError):
a.remove(x)
print(f"RESULT: {A1}")
output: RESULT: [[[3, 4, 6], [0, 3, 5]], [[3, 4, 6], [1, 3, 6]]]
Using list comprehension
[[list(set(A1[i][j])-set(J1[i][j])) for j in range(0,len(J1))] for i in range(0,len(A1))]
#output
[[[3, 4, 6], [0, 3, 5]], [[3, 4, 6], [1, 3, 6]]]

List item arrangement in python

I am looking for an efficient way to transform a given list into another list with degree n
here is input:
lst = [1, 2, 3, 4, 5, 6, 7]
n = 3
And favorable output is this:
[[1], [1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7], [7]]
It is basically like every element in resulting list is made of n consecutive elements from the given list except elements at starting and ending n-1 indices: 1, 2, 6, 7 in this example
Also for integer n, 1 <= n <= len(lst) is essential
You can use a comprehension with appropriate slices:
def chunks(lst, n=3):
return [lst[max(i,0):i+n] for i in range(1-n, len(lst))]
chunks([1, 2, 3, 4, 5, 6, 7])
# [[1], [1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7], [7]]
chunks([1, 2, 3, 4, 5], 4)
# [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5], [4, 5], [5]]
chunks([1, 2], 2)
# [[1], [1, 2], [2]]
chunks([1, 2, 3], 1)
# [[1], [2], [3]]
A more elegant version of this sliding window uses a collections.deque (as pointed out by #chepner in the comments):
from collections import deque
def chunks(lst, n=3):
window = deque(maxlen=n)
for x in lst:
window.append(x)
yield list(window)
while len(window) > 1:
window.popleft()
yield list(window)

.append() adding 2 values and deleting 1 previous value

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]]

Possible Combination of Lists inside a Single List

Given List
[[1,2],[3,4],[5,6]]
I want output as 3 different list as follows
[1,2,3,4],[3,4,5,6],[1,2,5,6]
You can use itertools.combinations to get all possible pairs
a = [[1, 2], [3, 4], [5, 6]]
>>> list(itertools.combinations(a, 2))
[([1, 2], [3, 4]), ([1, 2], [5, 6]), ([3, 4], [5, 6])]
To flatten the individual elements just map over them and add the two lists
>>> list(map(lambda x: x[0] + x[1], itertools.combinations(a, 2)))
[[1, 2, 3, 4], [1, 2, 5, 6], [3, 4, 5, 6]]
Simply Use Enumerate Function,
>>> x=[[1,2],[3,4],[5,6]]
>>> z = [x[index-len(x)] + x[index+1 - len(x)] for index, rec in enumerate(x)]
>>> z
>>> [[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 1, 2]]

I am trying to make a big list by using a present list but it's not working, can anybody explain why is this happening?

list1=[0,1,2]
mega_list=[]
for x in range(4):
print(list1)
mega_list.append(list1)
list1.pop(0)
list1.insert(2,list1[1]+1)
print(mega_list)
This is because you are adding a reference to list1 to mega_list. That is to say, at the end of the for loop you really have this:
mega_list = [list1, list1, list1, list1]
But, after the loop, list1 = [4, 5, 6], so that's why you get the output:
[[4, 5, 6], [4, 5, 6], [4, 5, 6], [4, 5, 6]]
To fix this, make a copy of the list before iterating further:
list1=[0,1,2]
mega_list=[]
for x in range(4):
print(list1)
mega_list.append(list1.copy())
list1.pop(0)
list1.insert(2, list1[1]+1)
print(mega_list)
Which outputs:
[0, 1, 2]
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]
list1=[0,1,2]
mega_list=[]
for x in range(4):
# Adds list1 as an element
mega_list.append(list1)
# Increments each element of list1
list1 = [x+1 for x in list1]
print(mega_list)
>>>[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]
You need to create a copy of the list, rather use the same instance in each append, e.g.:
list1=[0,1,2]
mega_list=[]
for x in range(5):
mega_list.append(list1[:])
list1.pop(0)
list1.insert(2,list1[1]+1)
print(mega_list) # [[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]
An alternative, is just use indexes into a full list of the input values, e.g.:
list1=list(range(7)) # [0,1,2,3,4,5,6]
mega_list=[]
for i in range(len(list1)-3+1):
mega_list.append(list1[i:i+3])
print(mega_list) # [[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]
One alternative is to create a generalized nwise() function using itertools:
import itertools as it
def nwise(iterable, n):
ts = it.tee(list1, n)
for c, t in enumerate(ts):
next(it.islice(t, c, c), None)
return zip(*ts)
list1 = list(range(7))
mega_list = [x for x in nwise(list1, 3)]
print(mega_list) # [(0, 1, 2), (1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6)]

Categories