Entering value in sublist if empty - python

So I have a larger for loop which produces nested lists of various of sizes: e.g.
[[6], [3], [5], [3, 2, 5, 3], [5], [6, 5, 4], [5, 3, 2]]
[[5], [], [], [4], [3]]
[[5], [2]]
[[], [4], [3, 2, 4]
In short, I would like it so that each array that has an empty sublist to simply be the value 0. So like :
If the list generated is :
[[6], [3], [5], [3, 2, 5, 3], [5], [6, 5, 4], [5, 3, 2]]
Then I would keep it that way.
But if the list generated is:[[5], [], [], [4], [3]]
Then I would like it to be:
[[5], [0], [0], [4], [3]]
Likewise, for the final row above, I would want it to be:[[0], [4], [3, 2, 4]
I have been trying something along the lines of :
for k in range(0,len(TempAisle)):
if TempAisle[k][0] == None:
TempAisle[k][0]= 0
k+=1
But I am getting an list index out of range error.
It seems to be a rather simple problem and have seen others who have asked ways to check if there is a sublist that is empty but I am having trouble replacing it with another value (0 in my case). Any help and explanation will be appreciated.

You can iterate on the items directly - the more Pythonic way - no need to use range. Test for the truthiness of each of the items (empty lists are falsy), and append a zero only if the sublist is empty:
for x in TempAisle:
if not x:
x.append(0)

For a one-line solution:
x = [elem or [0] for elem in TempAisle]
An EDIT based on the comment of #Moses Koledoye, to avoid creating a new list, but to keep it as a one-line solution:
[x.append(0) for x in TempAisle if not x]

Related

Understanding recursion using power set example

I have written a simple piece of code to print all subsets of a set using recursion. I have a hard time understanding the output. For example, the first line in the output shows an empty set and a singleton of 3 whereas I was expecting an empty set and singleton of 1 to be printed followed by an empty set, singleton of 1, singleton of 2 etc. However, that is not what gets printed. I do not know how to visualize recursion tree. Are there any general techniques to accomplish the visualisation? I tried drawing a tree but it quickly gets confusing.
def subsets(self, nums):
inp = nums
out = []
result=[]
def helper(inp,out,index):
if index==len(inp):
result.append(out)
return
helper(inp,out,index+1)
helper(inp,out+[inp[index]],index+1)
print(result)
helper(inp,out,0)
return result
The output from the print statement for the input '[1,2,3]' is shown below
[[], [3]]
[[], [3], [2], [2, 3]]
[[], [3], [2], [2, 3]]
[[], [3], [2], [2, 3], [1], [1, 3]]
[[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]
[[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]
[[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]
If you add an "indentation" parameter to your function, while you explore it, you can immediately see which function calls which:
def subsets(nums):
inp = nums
out = []
result=[]
def helper(indent,inp,out,index):
print(f"{indent}->helper({inp},{out},{index})")
if index==len(inp):
result.append(out)
return
helper(indent+'--',inp,out,index+1)
helper(indent+'--',inp,out+[inp[index]],index+1)
helper('',inp,out,0)
return result
The result will look like:
->helper([1, 2, 3],[],0)
--->helper([1, 2, 3],[],1)
----->helper([1, 2, 3],[],2)
------->helper([1, 2, 3],[],3)
------->helper([1, 2, 3],[3],3)
----->helper([1, 2, 3],[2],2)
------->helper([1, 2, 3],[2],3)
------->helper([1, 2, 3],[2, 3],3)
--->helper([1, 2, 3],[1],1)
----->helper([1, 2, 3],[1],2)
------->helper([1, 2, 3],[1],3)
------->helper([1, 2, 3],[1, 3],3)
----->helper([1, 2, 3],[1, 2],2)
------->helper([1, 2, 3],[1, 2],3)
------->helper([1, 2, 3],[1, 2, 3],3)
So you can immidiately see why you get [] first--you get it when you go all the way through the list without including anything in the results. You get [3] next because you backtrack to the call where you add 3 and then go to the end. You get [2] by backtracking a bit further, to where you include 2 in the output, and then down the path that doesn't add 3. Then you get [2,3] because you backtrack one level up, to the call that has 2 included in the result, and this time go to the path that adds 3.
It probably isn't the easiest way to compute a power-set, though. There is a one-to-one correspondence between the powerset of size n and the binary numbers between 0 and 2**n-1. For each number, the 1-bits indicate which elements to include in the set. So you can also compute the powerset like this:
def subsets(nums):
return [
[nums[j] for j, b in enumerate(reversed(format(i, 'b'))) if b == '1']
for i in range(2**len(nums))
]
It runs in exponential size, but so does the recursive version, and that is unavoidable when the output is exponential in the size of the input.

Using index from a list to get another value/element in another list

I have project wherein I have to get the index of certain element in a list, then use that index to get another value in another list.
For example,
j_set = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
on_going = [1]
e_list = [[], [1], [1], [2], [3], [3], [5], [4, 7], [6], [8, 9], [10]]
So far, the code looks like this:
if isinstance(on_going, int):
on_going = [on_going]
idx = [y for y, x in enumerate(e_list) if x in on_going] # code to get index in e_list
print(idx)
for i in idx:
q_active = j_set.append(i)
print(q_active)
The objective is to get the corresponding index of value/element in on_going from e_list. Then, use that index to get corresponding activity from j_set and store in q_active.
Expected output:
q_active = [2, 3]
The problem is, with the code above, I am getting an output for storing values in q_active as:
[1, 2] #idx output
None
None
Any help would be appreciated! Thanks!
Perhaps use a list_comprehension:
print([j_set[item] for i in on_going for item in range(len(e_list)) if i in e_list[item]])
#[2, 3]
You can use enumerate to get index and data from list:
e_list = [[], [1], [1], [2], [3], [3], [5], [4, 7], [6], [8, 9], [10]]
for data_index, data_val in enumerate(e_list):
print(data_index, data_val)
# write business logic here

How to convert a list of integer lists to an integer list Python? [duplicate]

This question already has answers here:
How do I make a flat list out of a list of lists?
(34 answers)
Closed 3 years ago.
I have a list of integer lists. I am trying to convert it to a list of integers.
int_list = [[0], [1], [2], [3], [4], [5], [6]]
new_list = []
for i in int_list:
new_list.append(i)
print(new_list)
Wanted output:
[0, 1, 2, 3, 4, 5, 6]
My output:
[[0], [1], [2], [3], [4], [5], [6]]
A very pythonic way of doing this would be to use list comprehension:
int_list = [[0], [1], [2], [3], [4], [5], [6]]
new_list = [value for sub_list in int_list for value in sub_list]
print(new_list)
An explaination of this can be found here: https://spapas.github.io/2016/04/27/python-nested-list-comprehensions/
There are many more ways that some people would prefer, for example a programmer who uses functional programming may prefer:
from operator import add
from functools import reduce
int_list = [[0], [1], [2], [3], [4], [5], [6]]
print(reduce(add, int_list))
If you want a more verbose and easier to understand version, you could use:
int_list = [[0], [1], [2], [3], [4], [5], [6]]
new_list = []
for i in int_list:
new_list.extend(i)
print(new_list)
You almost had it:
int_list = [[0], [1], [2], [3], [4], [5], [6]]
new_list = []
for i in int_list:
new_list.append(i[0])
print(new_list)
Output:
[0, 1, 2, 3, 4, 5, 6]
int_list = [[0], [1], [2], [3], [4], [5], [6]]
new_list = []
for i in int_list:
new_list += i
print(new_list)
1) you can use itemgetter with map
from operator import itemgetter
new_list = list(map(itemgetter(0), int_list))
print(new_list)
output:
[0, 1, 2, 3, 4, 5, 6]
2) or you can use chain from itertools
from itertools import chain
new_list = list(chain(*int_list))
print(new_list)
output:
[0, 1, 2, 3, 4, 5, 6]

Python: slice a matrix horizontally

Let's consider those two variables :
matrix = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]]
list_of_lengths = [2, 1, 1]
I am looking for a method to get this result :
result = [[[1, 2],
[5, 6],
[9, 10]], [[3],
[7],
[11]], [[4],
[8],
[12]]]
Indeed, I want three matrix as a result. The j-length of each one is determined by the variable list_of_lentghts.
I have already written a solution that works, but I would like to know if there is a solution more simple. Here is my solution:
def cut_matrix(matrix, list_of_lengths):
result = []
for a_len in list_of_lengths:
current_sub_matrix = []
for a_line in matrix:
current_new_line = []
for i in range(0, a_len):
current_new_line.append(a_line.pop(0))
current_sub_matrix.append(current_new_line)
result.append(current_sub_matrix)
return result
If you know the column offset i and the number of columns n, you can use slicing to obtain the columns:
[row[i:i+n] for row in matrix]
to get the slice. So you can simply use:
def cut_matrix(matrix, list_of_lengths):
result = []
col = 0
for a_len in list_of_lengths:
result.append([row[col:col+a_len] for row in matrix])
col += a_len
return result
It generates:
>>> cut_matrix(matrix,list_of_lengths)
[[[1, 2], [5, 6], [9, 10]], [[3], [7], [11]], [[4], [8], [12]]]
This will also work faster than using .pop(0) since popping from the front is done in O(n) (so popping all elements requires O(n2) whereas slicing all elements is done in O(n)). Finally it leaves the original matrix intact which is thus more declarative.

python - Concatenate list elements in every possible way

My issue might be quite difficult to explain (maybe that's also the reason I did not find a solution or a similar problem).
What I have is a list with some elements (in my specific case also lists).
What I want is having every possible combinations of concatenations of this list in the same order.
For example:
[[1], [2], [3], [4]] # what I have
{ # what I want
[[1], [2], [3], [4]],
[[1, 2], [3], [4]],
[[1], [2, 3], [4]],
[[1], [2], [3, 4]],
[[1, 2], [3, 4]], # Update 1
[[1, 2, 3], [4]],
[[1], [2, 3, 4]],
[[1, 2, 3, 4]]
}
In general the length of the sublists is greater then 1; also the list itself may have more than 4 elements.
Any help is highly appreciated.
UPDATE 1:
added missing combination in code.
Try this:
def concats(l):
if len(l) < 2:
return [l]
return [[l[0]] + x for x in concats(l[1:])] + \
concats([l[0] + l[1]] + l[2:])
Here's a sample case:
l = [[1], [2], [3], [4]]
r = concats(l)
And the result:
[[[1], [2], [3], [4]],
[[1], [2], [3, 4]],
[[1], [2, 3], [4]],
[[1], [2, 3, 4]],
[[1, 2], [3], [4]],
[[1, 2], [3, 4]],
[[1, 2, 3], [4]],
[[1, 2, 3, 4]]]
Edit: It wasn't clear to me how the empty list should be handled, but in that case you may want to simply return an empty list without wrapping it in an outer list - I'll leave that case up to you. A simple check at the top of the function can handle it any way you choose (and it won't affect the larger cases).

Categories