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]]]
Related
I have three lists as follows.
A = [1, 2, 3]; B = [[3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3]]; C = [[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
I want to create another list containing all the above inner lists starting from A to C.
Desired = [elements of A, elements of B, elements of C] just like this.
Desired = [[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3], [2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
It seems like you know which list is nested (B and C) and which isn't (A). If that's the case then you could simply do:
result = [A] + B + C
If you don't know but can determine the nestedness by looking at the first item, then you could do:
result = [
item
for numbers in (A, B, C)
for item in (numbers if isinstance(numbers[0], list) else [numbers])
]
If that's also not the case, i.e. there could be mixed lists (lists that contain numbers and lists), then you could use itertools.groupby from the standard library:
from itertools import groupby
result = []
for key, group in groupby(A + B + C, key=lambda item: isinstance(item, list)):
if not key:
group = [[*group]]
result.extend(group)
Results for all versions (with A, B and C like provided):
[[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3],
[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
The method I use below is to see if the inner_list contents are infact a list of themselves.
If they are, then append the inner list.
If they are not, then append the outer_list.
A = [1, 2, 3];
B = [[3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3]];
C = [[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
desired = []
for outer_list in (A,B,C):
list_state = False
for inner_list in outer_list:
if isinstance(inner_list, list):
desired.append(inner_list)
else:
list_state = True
# Add outer_list only if the inner_list was not a list
if list_state:
desired.append(outer_list)
print(desired)
OUTPUT:
[[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3], [2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
I made something to make a list to an nested list if it is not.
A = [1, 2, 3]
B = [[3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3]]
C = [[2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
listt = [ 'A', 'B', 'C' ]
des = []
for i in listt:
if type((globals()[i])[0]) != list:
globals()[i] = [[i for i in globals()[i]]] #turns into nested list if not (line 7-9)
for i in (A,B,C):
for x in i:
des.append(x)
print(des)
Output:
[[1, 2, 3], [3, 4, 5], [4, 5, 6], [4, 5, 7], [7, 4, 3], [2, 3, 1], [2, 3, 3], [2, 4, 5], [4, 5, 6], [7, 3, 1]]
I have a nested array of arbitrary length and trying to retrieve data from it in the following order: items in the [0] element of the array form somewhat like a tree and as a result I should return all possible combinations with them.
For example:
some_list = [[1, 2], [3, 4], [5, 6, 7]]
the result should be:
[1, 3, 5], [1, 3, 6], [1, 3, 7], [1, 4, 5], [1, 4, 6], [1, 4, 7],
[2, 3, 5], [2, 3, 6], [2, 3, 7], [2, 4, 5], [2, 4, 6], [2, 4, 7]
I tried loops but they do not seem a good decision.
I think it should be recursion, but don't know how to apply it.
this is an example of a recursive function that would calculate the cartesian product of all the input lists
def cp(x):
l = []
# loop over the lists in the list
# if there is only 1 list left in the input then return it
if len(x) > 1:
for i in x[0]: # loop over the first list in the input
for j in cp(x[1:]): # loop over the cartesian product of the remaining lists in the input
l.append([i]) # add a new sub-list starting with value of i
if isinstance(j,list): # extend it with the result of the cartesian product of the remaining lists
l[-1].extend(j)
else:
l[-1].append(j)
else:
l = x[0]
return l
print(cp([[1, 2], [3, 4], [5, 6, 7]]))
gives the output
[[1, 3, 5], [1, 3, 6], [1, 3, 7], [1, 4, 5], [1, 4, 6], [1, 4, 7], [2, 3, 5], [2, 3, 6], [2, 3, 7], [2, 4, 5], [2, 4, 6], [2, 4, 7]]
have a look here for implementations in different programming languages:
https://rosettacode.org/wiki/Cartesian_product_of_two_or_more_lists
You can do it with nested for loops, or for convenience, with itertools.product:
from itertools import product
some_list = [[1, 2], [3, 4], [5, 6, 7]]
prod = [list(i) for i in product(*some_list)]
print(prod)
Output:
[[1, 3, 5], [1, 3, 6], [1, 3, 7], [1, 4, 5], [1, 4, 6], [1, 4, 7], [2, 3, 5], [2, 3, 6], [2, 3, 7], [2, 4, 5], [2, 4, 6], [2, 4, 7]]
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)
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]]
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)]