I have a nested list:
x = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
I want to iterate over the list and return a new nested list with each list returned with one value missing. So:
new_x = [[2,3,4],[1,3,4],[1,2,4],[1,2,3]]
I have this:
temp_list = []
y = 0
for i in x:
temp_list += i.remove(y)
y+=1
print(x)
But what's happening is each iteration is removing the indexed item so the list goes out of range.
list = [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
for count, i in enumerate(list):
if len(i) > 0:
del i[count]
print(list)
For each sublist it deletes the element with an index equal to the index of the sublist
>>>[[2, 3, 4], [1, 3, 4], [1, 2, 4], [1, 2, 3]]
Hope this helps!
You have to use pop instead for remove. See this one:
In [46]: x = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
In [47]: new_list = [lst for ind, lst in enumerate(x) if lst.pop(ind)]
In [48]: new_list
Out[48]: [[2, 3, 4], [1, 3, 4], [1, 2, 4], [1, 2, 3]]
x = [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]
for i in range(0,len(x)):
for j in range (0,len(x)):
if(i==j):
del(x[i][j])
print(x)
new_x = [[2,3,4],[1,3,4],[1,2,4],[1,2,3]]
del(x[i][j]) is used to delete by index from list
Related
I searched the net but couldn't find anything. I am trying to get all possible combinations including all subsets combinations of two lists (ideally n lists). All combinations should include at least one item from each list.
list_1 = [1,2,3]
list_2 = [5,6]
output = [
[1,5], [1,6], [2,5], [2,6], [3,5], [3,6],
[1,2,5], [1,2,6], [1,3,5], [1,3,6], [2,3,5], [2,3,6], [1,5,6], [2,5,6], [3,5,6],
[1,2,3,5], [1,2,3,6],
[1,2,3,5,6]
]
All I can get is pair combinations like [1,5], [1,6], .. by using
combs = list(itertools.combinations(itertools.chain(*ls_filter_columns), cnt))
What is the pythonic way of achieving this?
Here is one way:
from itertools import combinations, product
def non_empties(items):
"""returns nonempty subsets of list items"""
subsets = []
n = len(items)
for i in range(1,n+1):
subsets.extend(combinations(items,i))
return subsets
list_1 = [1,2,3]
list_2 = [5,6]
combs = [list(p) + list(q) for p,q in product(non_empties(list_1),non_empties(list_2))]
print(combs)
Output:
[[1, 5], [1, 6], [1, 5, 6], [2, 5], [2, 6], [2, 5, 6], [3, 5], [3, 6], [3, 5, 6], [1, 2, 5], [1, 2, 6], [1, 2, 5, 6], [1, 3, 5], [1, 3, 6], [1, 3, 5, 6], [2, 3, 5], [2, 3, 6], [2, 3, 5, 6], [1, 2, 3, 5], [1, 2, 3, 6], [1, 2, 3, 5, 6]]
Which has more elements then the output you gave, though I suspect that your intended output is in error. Note that my code might not correctly handle the case in which there is a non-empty intersection of the two lists. Then again, it might -- you didn't specify what the intended output should be in such a case.
Here is another way.
Even though it is not fancy, it cares n_lists easily.
def change_format(X):
output = []
for x in X:
output += list(x)
return output
import itertools
list_1 = [1,2,3]
list_2 = [5,6]
list_3 = [7,8]
lists = [list_1, list_2, list_3]
lengths = list(map(len, lists))
rs_list = itertools.product(*[list(range(1, l+1)) for l in lengths])
output = []
for rs in rs_list:
temp = []
for L, r in zip(lists, rs):
temp.append(list(itertools.combinations(L, r)))
output += list(itertools.product(*temp))
output = list(map(change_format, output))
I have managed to make it work for n-lists with less code, which was a challenge for me.
from itertools import chain, combinations, product
def get_subsets(list_of_lists):
"""
Get all possible combinations of subsets of given lists
:param list_of_lists: consists of any number of lists with any number of elements
:return: list
"""
ls = [chain(*map(lambda x: combinations(e, x), range(1, len(e)+1))) for e in list_of_lists if e]
ls_output = [[i for tpl in ele for i in tpl] for ele in product(*ls)]
return ls_output
list_1 = [1, 2, 3]
list_2 = [5, 6]
list_3 = [7, 8]
ls_filter_columns = [list_1, list_2, list_3]
print(get_subsets(ls_filter_columns))
I have two for loop to select items from a list and don't want to repeat [1,2] and [2,1] similar is the case for other elements. Basically I have
for i in range(0,20):
for j in range(0,20):
if (i != j):
function(list[i],list[j])
The output from [1,2] and [2,1] gives the same results and I don't want to repeat that. basically i and j are identical array. I eliminate similar elements using if loop.And I want to eliminate repeated elements.
Simply start your j loop from i.
lis = []
for i in range(0, 5):
for j in range(i + 1, 5):
lis.append([i, j])
This outputs
[[0, 1],
[0, 2],
[0, 3],
[0, 4],
[1, 2],
[1, 3],
[1, 4],
[2, 3],
[2, 4],
[3, 4]]
For a smaller output, I changed 20 to 5.
How to merge two array and group by key?
Example:
my_list = [3, 4, 5, 6, 4, 6, 8]
keys = [1, 1, 2, 2, 3, 5, 7]
Expected outcome:
[[1, 3, 4], [2, 5, 6], [3, 4], [5, 6], [7, 8]]
If I understand it right, the list of keys map to the list of values. You can use the zip function to iterate through two lists at the same time. Its convenient in this case. Also check up on the beautiful defaultdict functionality - we can use it to fill a list without initialising it explicitely.
from collections import defaultdict
result = defaultdict(list) # a dictionary which by default returns a list
for key, val in zip(keys, my_list):
result[key].append(val)
result
# {1: [3, 4], 2: [5, 6], 3: [4], 5: [6], 7: [8]}
You can then go to a list (but not sure why you would want to) with:
final = []
for key, val in result.items():
final.append([key] + val) # add key back to the list of values
final
# [[1, 3, 4], [2, 5, 6], [3, 4], [5, 6], [7, 8]]
I think you have to write it by your own using set() to remove duplicates, so I have made a function called merge_group
my_list = [3, 4, 5, 6, 4, 6, 8]
keys = [1, 1, 2, 2, 3, 5, 7]
def merge_group(input_list : list, input_key : list):
result = []
i = 0
while i < len(my_list):
result.append([my_list[i], keys[i]])
i += 1
j = 0
while j < len(result):
if j+1 < len(result):
check_sum = result[j] + result[j+1]
check_sum_set = list(set(check_sum))
if len(check_sum) != len(check_sum_set):
result[j] = check_sum_set
j += 1
return result
print(merge_group(my_list, keys))
How will i access the list in a list?
For example
data = [ [[list([1,2,3]), list([0,1])]], [[list([4,5,6]), list([1,1])]] ]
The output data should be
output = [[1,2,3],[4,5,6]]
Access individual lists as follows by index.
data[0] = [[[1, 2, 3], [0, 1]]]
data[0][0] = [[1, 2, 3], [0, 1]]
data[0][0][0] = [1, 2, 3]
data[1][0][0] = [4, 5, 6]
This is what i did
>>> data = [ [[list([1,2,3]), list([0,1])]], [[list([4,5,6]), list([1,1])]] ]
>>> output = list([row[0][0] for row in data])
>>> print (output)
[[1, 2, 3], [4, 5, 6]]
I have a really weird issue in Python3. I have some code that generates some different list from a list of integers (what this does exactly is not relevant).
def get_next_state(state):
max_val = max(state)
max_index = state.index(max_val)
new_state = state
for n in range(max_val + 1):
new_state[max_index] -= 1
new_state[(n + max_index) % len(state)] += 1
return new_state
Now all I want to do is add a next state to some list that keeps the states. This is my code:
l = [0, 2, 7, 0]
seen_states = []
for _ in range(10):
print(l)
seen_states += [l]
l = get_next_state(l)
print(seen_states)
For some reason list l is assigned correctly when I print it, but it is not added correctly to the list of seen states. Note that I have also tried seen_states.append(l) instead of using += [l]. Does anyone know why this happend?
To prevent these problems use copy, deepcopy or list[:]
import copy
def get_next_state(state):
max_val = max(state)
max_index = state.index(max_val)
new_state = copy.deepcopy(state)
for n in range(max_val + 1):
new_state[max_index] -= 1
new_state[(n + max_index) % len(state)] += 1
return new_state
You are sending your list l inside the function. When you assign it to another name, you are not making a copy but referencing the original object. Any modification on these lists is a change in the original object.
Using new_state = state[:] (copies the list instead of referencing the original) in the get_next_state produces the following output:
[0, 2, 7, 0]
[2, 4, 1, 2]
[3, 1, 2, 3]
[0, 2, 3, 4]
[1, 3, 4, 1]
[2, 4, 1, 2]
[3, 1, 2, 3]
[0, 2, 3, 4]
[1, 3, 4, 1]
[2, 4, 1, 2]
[[0, 2, 7, 0], [2, 4, 1, 2], [3, 1, 2, 3], [0, 2, 3, 4], [1, 3, 4, 1], [2, 4, 1, 2], [3, 1, 2, 3], [0, 2, 3, 4], [1, 3, 4, 1], [2, 4, 1, 2]]
Not sure if this is your desired output, as you did not specify what you are getting as "wrong" output