make a list inside of a list using loops - python

I'm trying to make a function that returns a list of n elements like the following:
factorial_list(4) → [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
my output is [[1], [1], [2], [1], [2], [3], [1], [2], [3], [4]]
As you see I'm struggling to make the order of the inner lists. Any insights to what I should change in my code?
def factorial_list(n):
list2=[]
for i in range(1,n+1):
for j in range(1,i+1):
list2.append([j])
print(list2)
factorial_list(4)

Method 1: based on the logic of your code
def factorial_list(n):
final_list = []
for i in range(1, n+1):
temp = []
for j in range(1, i+1):
temp.append(j)
final_list.append(temp)
print(final_list)
factorial_list(4) # [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
Method 2: a mix of for loop and list comprehensions
def factorial_list(n):
final_list = []
for i in range(1, n+1):
temp = [j for j in range(1, i+1)]
final_list.append(temp)
print(final_list)
factorial_list(4) # [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
Method 3: using list comprehensions
def factorial_list(n):
final_list = [[j for j in range(1, i+1)] for i in range(1, n+1)]
print(final_list)
factorial_list(4) # [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]

You need to create a new list for each iteration of the first loop:
def factorial_list(n):
list2=[]
for i in range(1,n+1):
list3 = [] # <--- Create a new list for each iteration
for j in range(1,i+1):
list3.append(j)
list2.append(list3)
print(list2)
factorial_list(4)
# Output: [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]

Related

generate combinations from list of numbers

generate all combinations from list of numbers,the combinations can be pair of two numbers
example 1 : list of 2 numbers [1,2]
[
[[1],[2]],
[[1,2]]
]
example 2 : list of 3 numbers [1,2,3]
[
[[1], [2], [3]],
[[1], [2, 3]],
[[1, 3], [2]],
[[1, 2], [3]]
]
example 3 : list of 4 numbers [1,2,3,4]
[
[[1], [2], [3], [4]]
[[1], [2], [3, 4]],
[[1], [2, 4], [3]],
[[1], [2, 3], [4]],
[[1, 4], [2], [3]],
[[1, 3], [2], [4]],
[[1, 2], [3], [4]],
[[1, 2], [3, 4]],
[[1, 3], [2, 4]],
[[1, 4], [2, 3]]
]
The current implementation works but it is slow for list of 10 numbers
def get_all_order_combinations(nums, first=True):
if first and len(nums) == 1:
return [[[nums[0]]]]
if len(nums) == 2:
nums.sort()
return [
[[nums[0]], [nums[1]]],
[[nums[0], nums[1]]]
]
else:
all_results = []
for i in range(0, len(nums)):
temp_list = list(nums)
del temp_list[i]
current_num = nums[i]
results = get_all_order_combinations(temp_list, False)
results = [[[current_num]]+result for result in results]
for result in results:
result.sort()
if result not in all_results:
all_results.append(result)
if len(nums) >= 4:
for comb in combinations(nums, 2):
comb = list(comb)
results = get_all_order_combinations(
[n for n in nums if n not in comb]
,False
)
results = [[comb]+result for result in results]
for result in results:
result.sort()
if result not in all_results:
all_results.append(result)
return all_results
Try using the python in-built "itertools" package.
It is optimised to create combinations, which may solve your concerns with speed. Online searches will yield results on how to use it.
Here is one example:
geeksforgeeks Permutation and Combination in Python with itertools
My attempt at reproducing example 2 using itertools:
from itertools import combinations
num_list = [1, 2, 3]
output_list = []
for i in range(1, len(num_list)):
comb = combinations(num_list, i)
obtained_combinations = []
for combination in list(comb):
if i != 1:
temp_list = num_list.copy()
for selected_number in combination:
temp_list.remove(selected_number)
obtained_combinations.append([temp_list, list(combination)])
else:
obtained_combinations.append(list(combination))
output_list.append(obtained_combinations)
print(output_list)
Output:
[[[1], [2], [3]], [[[3], [1, 2]], [[2], [1, 3]], [[1], [2, 3]]]]

how to improve list generator function

the purpose of the below function is to return:
> f(0) returns [],
> f(1) returns [[1]]
> f(2) returns [[1], [1,2]]
> f(3) returns [[1], [1,2], [1,2,3]]
how can it be improved?
def list_generator(number: int) -> list:
if number == 0:
new_list = []
else:
temp_list = []
new_list = [0] * number
for idx, num in zip(range(len(new_list)), range(1, number + 1)):
temp_list.append(num)
new_list[idx] = list(set(temp_list))
return new_list
def f(n):
return [[x + 1 for x in range(i)] for i in range(1, n + 1)]
for n in range(6):
print(n, f(n))
# 0 []
# 1 [[1]]
# 2 [[1], [1, 2]]
# 3 [[1], [1, 2], [1, 2, 3]]
# 4 [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
# 5 [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
You can use a list comprehension:
def f(number: int) -> list:
return [list(range(1, i+1)) for i in range(1, number+1)]

How to get all consecutive sequences of numbers from given set of numbers?

I will start the description of the problem with an example so that the question is clear.
List of numbers: [1,2,3,4]
How can I get each successive string: [[1],[1,2],[1,2,3],[1,2,3,4],[2],[2,3],[2,3,4],[3],[3,4],[4]]
I've been trying to solve this problem for a while and managed to get [[1, 2, 3, 4], [2, 3, 4], [3, 4], [4]] with lots of useless repetitions.
list = [1,2,3,4]
i = 0
j = 0
tempList = []
sequancesList = []
while i < len(list):
while j < len(list):
tempList.append(list[j])
sequancesList.append(tempList)
j += 1
i += 1
j = i
tempList = []
def deleteDuplicates(list):
noduplist = []
for element in list:
if element not in noduplist:
noduplist.append(element)
return noduplist
finalSequancesList = deleteDuplicates(sequancesList)
print(finalSequancesList)
Here's how to do it:
list = [1,2,3,4]
sequancesList = []
for i in range(len(list)):
tmp = []
for j in range(i,len(list)):
tmp.append(list[j])
sequancesList.append(tmp[:])
print(sequancesList)
-> [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [2], [2, 3], [2, 3, 4], [3], [3, 4], [4]]
Here is a generator that does exactly that:
def iter_successive(input_list):
for i in range(len(input_list)):
for j in range(i+1,len(input_list)+1):
yield input_list[i:j]
>>> list(iter_successive(input_list))
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [2], [2, 3], [2, 3, 4], [3], [3, 4], [4]]
Comparable one-liner solution:
def iter_successive(input_list):
return (input_list[i:j] for i in range(len(input_list))
for j in range(i+1,len(input_list)+1))
Edit: As was stated in the comments, the approach below works only if the list contains whole, ascending numbers and not in other instances.
There are two ways to do this, either as a nested for-loop or a one-liner using list-comprehension. Both versions below:
Nested for-loop
nrs = list(range(1,5))
result = []
for i in nrs:
for j in range(i, max(nrs)+1):
result.append(list(range(i,j+1)))
print(result)
List-comprehension
result = [list(range(i,j+1)) for i in nrs for j in range(i, max(nrs)+1)]
print(result)

List all contiguous sub-arrays

I have an array [1, 2, 3] of integer and I need to return all the possible combination of contiguous sub-arrays of this array.
[[1],[2],[3],[1,2],[2,3],[1,2,3]]
How can I handle that with python? One way would be to have 2 loops and the array itself but there should be a better way.
One line solution (I don't know what means "better way" for you)
L = [1,2,3]
[L[i:i+j] for i in range(0,len(L)) for j in range(1,len(L)-i+1)]
L=[1,2,3,4]
[L[i:i+j] for i in range(0,len(L)) for j in range(1,len(L)-i+1)]
you get,
[[1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]
[[1],
[1, 2],
[1, 2, 3],
[1, 2, 3, 4],
[2],
[2, 3],
[2, 3, 4],
[3],
[3, 4],
[4]]
Simplifying the Inspector's solution:
def getAllWindows(L):
for w in range(1, len(L)+1):
for i in range(len(L)-w+1):
yield L[i:i+w]
And a solution using no loops at all:
def allSubArrays(L,L2=None):
if L2==None:
L2 = L[:-1]
if L==[]:
if L2==[]:
return []
return allSubArrays(L2,L2[:-1])
return [L]+allSubArrays(L[1:],L2)
def kwindow(L, k):
for i in range(len(L)-k+1):
yield L[i:i+k]
def getAllWindows(L):
for w in range(1, len(L)+1):
yield from kwindow(L, w)
Ouput:
In [39]: for i in getAllWindows([1,2,3]): print(i)
[1]
[2]
[3]
[1, 2]
[2, 3]
[1, 2, 3]
An itertools based approach:
import itertools
def allSubArrays(xs):
n = len(xs)
indices = list(range(n+1))
for i,j in itertools.combinations(indices,2):
yield xs[i:j]
For example:
>>> list(allSubArrays([1,2,3]))
[[1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]
li=[1,2,3]
l=[]
for i in range(length(li)):
for j in range(i,len(li)+1):
if i==j: *cancelling empty sublist item*
continue
else:
subli=li[i:j]
l.append(subli)
print(l)
output:
[[1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]

How to obtain sliced sublists of a list dynamically in python?

Let's say I have a list:
l = [0,1,2,3,4]
And I want to obtain a sequence of lists in this logic:
[[1,2,3,4],[0,1,2,3],[2,3,4],[1,2,3],[0,1,2],[3,4],[2,3],[1,2],[0,1],[0],[1],[2],[3],[4]]
That's it, sublists made of l[1:] and l[:-1]
I started by this recursive function:
l = [0,1,2,3,4]
def sublist(l):
if len(l) == 1:
return l
else:
return [sublist(l[1:]),sublist(l[:-1])]
a = [sublist(l)]
print a
But it's not really what I what as it outputs:
[[[[[[4], [3]], [[3], [2]]], [[[3], [2]], [[2], [1]]]], [[[[3], [2]], [[2], [1]]], [[[2], [1]], [[1], [0]]]]]]
import itertools
[list(itertools.combinations(l, x)) for x in range(1, len(l))]
Here's a very straightforward implementation:
def sublists_n(l, n):
subs = []
for i in range(len(l)-n+1):
subs.extend([l[i:i+n]])
return subs
def sublists(l):
subs = []
for i in range(len(l)-1,0,-1):
subs.extend(sublists_n(l,i))
return subs
>>> l = [0,1,2,3,4]
>>> sublists(l)
[[0, 1, 2, 3], [1, 2, 3, 4], [0, 1, 2], [1, 2, 3], [2, 3, 4], [0, 1], [1, 2], [2, 3], [3, 4], [0], [1], [2], [3], [4]]
[l[x:] for x in range(len(l))] + [l[:x+1] for x in range(len(l))]
Loops through l twice, but you sort of have to no matter what I think (could use zip but same thing).
A simple recursion, doesn't quite order things correctly but its simple.
def sublists(l):
right = l[1:]
left = l[:-1]
result = [right, left]
if len(l) > 2:
result.extend(sublists(right))
result.extend(sublists(left))
return result
print sublists([0,1,2,3,4])

Categories

Resources