Generates the power set of the set without using pre-defined library? - python

I am trying to generate the power set of the list,without using any library.
For example, given the set {1, 2, 3}, it should return {{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}
Note: We can use list also for it.
I have implemented the code , but it is not dynamic , it is for the specific length . How can I make it dynamic.
Code:
my_list = [0, 1, 2, 3]
first_list = []
second_list = [[]]
final_list = []
for iterate in my_list:
second_list.append([iterate])
for outer_loop in my_list:
for inner_loop in my_list:
if outer_loop!=inner_loop:
first_list.append([outer_loop, inner_loop])
result = (second_list + first_list)
for iterated in result:
if sorted(iterated) not in final_list:
final_list.append(iterated)
final_list + [my_list]

Try this:
def get_powerset(s):
x = len(s)
subsets = []
for i in range(1 << x):
subsets.append([s[j] for j in range(x) if (i & (1 << j))])
return subsets
lists = [[1, 2, 3], [0, 1, 2, 3]]
for num_list in lists:
print(get_powerset(num_list))
Output:
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
[[], [0], [1], [0, 1], [2], [0, 2], [1, 2], [0, 1, 2], [3], [0, 3], [1, 3], [0, 1, 3], [2, 3], [0, 2, 3], [1, 2, 3], [0, 1, 2, 3]]

In addition to #Sabil's answer, a recursive approach:
def get_powerset(s):
if len(s) == 0:
return []
if len(s) == 1:
return [s]
without_s0 = get_powerset(s[1:])
with_s0 = [subs + [s[0]] for subs in without_s0]
return with_s0 + without_s0
This solution assumes a item method, but that can be easily relaxed.

Related

How to group lists with common elements into dict using functional approach in python?

I am trying to aggregate lists into dict. First column can be treated as id and second column as some random element. I want all elements assigned to the same id to be grouped in a list under that id. Id=None, empty lists need to be filtered out and not allow duplicate elements.
Probably seeing input and output will be more expressive
This is input:
[
[1, 1],
[2, 1],
[2, 2],
[2, 3],
[2, 3],
[2, 4],
[],
[None, 5]
]
This is expected output:
{
1: [1],
2: [1, 2, 3, 4]
}
I got stuck at this functional and imperative hybrid:
filtered_groups = list(filter(lambda group: len(group) == 2 and group[0] is not None, groups))
grouper = {}
for group in filtered_groups:
id = group[0]
element = group[1]
grouper_entry = grouper.get(id)
if not grouper_entry:
grouper_entry = grouper[id] = []
if element not in grouper_entry:
grouper_entry.append(element)
expected_result = {
1: [1],
2: [1, 2, 3, 4]
}
assert grouper == expected_result
How can I rewrite this for loop into mapping/reducing/grouping function to achieve expected result?
Try:
lst = [[1, 1], [2, 1], [2, 2], [2, 3], [2, 3], [2, 4], [], [None, 5]]
out, seen = {}, set()
for a, b in (item for item in lst if len(item) == 2 and item[0] is not None):
if (a, b) not in seen:
out.setdefault(a, []).append(b)
seen.add((a, b))
print(out)
Prints:
{1: [1], 2: [1, 2, 3, 4]}
A solution using defaultdict
from collections import defaultdict
lst = [[1, 1], [2, 1], [2, 2], [2, 3], [2, 3], [2, 4], [], [None, 5]]
dic = defaultdict(list)
for sublist in lst:
if (len(sublist) == 2):
if sublist[0] != None:
id, val = sublist
dic[id].append(val)
print(dic)

implementation error in Python recursive expression

I'm solving the problem.
You have to leave the last list, but the previous list is printed out again.
def merge(xs,ys):
# xs, ys, ss = xs, ys, []
xs, ys, ss = xs[:], ys[:], []
while xs!=[] and ys!=[]:
if xs[0] <= ys[0]:
ss.append(xs[0])
xs.remove(xs[0])
else:
ss.append(ys[0])
ys.remove(ys[0])
ss.extend(xs)
ss.extend(ys)
return ss
accumulator = []
remain = []
def merge2R(xss):
if len(xss)% 2 != 0 :
OExcept = len(xss)-1
remain.append((xss[OExcept]))
xss.remove(xss[OExcept])
if xss != []:
accumulator.append(merge(xss[0],xss[1]))
xss.remove(xss[0])
xss.remove(xss[0])
return merge2R(xss)
else:
return accumulator + remain
The result comes out like this.
How can I fix it?
>>> merge2R([[2],[1,3],[4,6,7],[5,8],[9]])
[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3], [4, 5, 6, 7, 8], [9]]
Desired result value:
>>> merge2R([[2],[1,3],[4,6,7],[5,8]])
[[1,2,3], [4,5,6,7,8]]
>>> merge2R([[2],[1,3],[4,6,7],[5,8],[9]])
[[1,2,3], [4,5,6,7,8], [9]]
Your code was working, you just needed to reset accumulator and remain
def merge2R(xss):
# Declare use of globals
global remain
global accumulator
if len(xss) % 2 != 0:
OExcept = len(xss)-1
remain.append((xss[OExcept]))
xss.remove(xss[OExcept])
if xss != []:
accumulator.append(merge(xss[0], xss[1]))
xss.remove(xss[0])
xss.remove(xss[0])
return merge2R(xss)
else:
x = accumulator + remain
# Must reset accumulator and remain
accumulator = []
remain = []
return x
Because you initialise both arrays as empty, then append to them:
# Remain
remain.append((xss[OExcept]))
# Accumulator
accumulator.append(merge(xss[0], xss[1]))
After you have finished with the data in those arrays (at end of function) you need to discard it:
accumulator = []
remain = []
The result of not discarding these arrays is evident when calling the function with the same argument multiple times:
print(merge2R([[2], [1, 3]]))
print(merge2R([[2], [1, 3]]))
print(merge2R([[2], [1, 3]]))
print(merge2R([[2], [1, 3]]))
print(merge2R([[2], [1, 3]]))
[[1, 2, 3]]
[[1, 2, 3], [1, 2, 3]]
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]

Why do the two following lines of code give different results? [duplicate]

This question already has answers here:
Does Python make a copy of objects on assignment?
(5 answers)
Closed 1 year ago.
I wanted to build a function that finds all the possible subsets of a set.
The first function works well, while the second doesn't. In the first I used a list comprehension to remove the first element of a list, while in the second I used pop(0). Why do they output different results?
The first function is:
def combinations(n):
if len(n) == 1:
return [[], n]
a = [element for element in n if element != n[0]]
return [[n[0]] + comb for comb in combinations(a)] + combinations(a)
The second function is:
def combinations(n):
if len(n) == 1:
return [[], n]
a = n
a.pop(0)
return [[n[0]] + comb for comb in combinations(a)] + combinations(a)
The output of the first is:
[[0, 1, 2], [0, 1, 2, 3], [0, 1], [0, 1, 3], [0, 2], [0, 2, 3], [0], [0, 3], [1, 2], [1, 2, 3], [1], [1, 3], [2], [2, 3], [], [3]]
The output of the second is:
[[3, 3, 3], [3, 3, 3, 3], [3, 3], [3, 3, 3], [3], [3, 3], [], [3]]
Already answered in the comments. In addition, this should solve the problem.
def combinations(n):
if len(n) == 1:
return [[], n]
a = list(n)
a.pop(0)
return [[n[0]] + comb for comb in combinations(a)] + combinations(a)

How to pack consecutive duplicates of list elements into sublists?

How can I "pack" consecutive duplicated elements in a list into sublists of the repeated element?
What I mean is:
l = [1, 1, 1, 2, 2, 3, 4, 4, 1]
pack(l) -> [[1,1,1], [2,2], [3], [4, 4], [1]]
I want to do this problem in a very basic way as I have just started i.e using loops and list methods. I have looked for other methods but they were difficult for me to understand
For removing the duplicates instead of packing them, see Removing elements that have consecutive duplicates
You can use groupby:
from itertools import groupby
def pack(List):
result = []
for key, group in groupby(List):
result.append(list(group))
return result
l = [1, 1, 1, 2, 2, 3, 4, 4, 1]
print(pack(l))
Or one-line:
l = [1, 1, 1, 2, 2, 3, 4, 4, 1]
result = [list(group) for key,group in groupby(l)]
# [[1, 1, 1], [2, 2], [3], [4, 4], [1]]
You can use:
lst = [1, 1, 1, 2, 2, 3, 4, 4, 1]
# bootstrap: initialize a sublist with the first element of lst
out = [[lst[0]]]
for it1, it2 in zip(lst, lst[1:]):
# if previous item and current one are equal, append result to the last sublist
if it1 == it2:
out[-1].append(it2)
# else append a new empty sublist
else:
out.append([it2])
Output:
>>> out
[[1, 1, 1], [2, 2], [3], [4, 4], [1]]
This code will do:
data = [0,0,1,2,3,4,4,5,6,6,6,7,8,9,4,4,9,9,9,9,9,3,3,2,45,2,11,11,11]
newdata=[]
for i,l in enumerate(data):
if i==0 or l!=data[i-1]:
newdata.append([l])
else:
newdata[-1].append(l)
#Output
[[0,0],[1],[2],[3],[4,4],[5],[6,6,6],[7],[8],[9],[4,4],[9,9,9,9,9],[3,3],[2],[45],[2],[11,11,11]]

Python: how to splice a list into sublists of given lengths?

x = [2, 1, 2, 0, 1, 2, 2]
I want to splice the above list into sublists of length = [1, 2, 3, 1]. In other words, I want my output to look something like this:
[[2], [1, 2], [0, 1, 2], [2]]
where my first sublist is of length 1, the second sublist is of length 2, and so forth.
You can use itertools.islice here to consume N many elements of the source list each iteration, eg:
from itertools import islice
x = [2, 1, 2, 0, 1, 2, 2]
length = [1, 2, 3, 1]
# get an iterable to consume x
it = iter(x)
new_list = [list(islice(it, n)) for n in length]
Gives you:
[[2], [1, 2], [0, 1, 2], [2]]
Basically we want to extract certain lengths of substrings.
For that we need a start_index and an end_index. The end_index is your start_index + the current length which we want to extract:
x = [2, 1, 2, 0, 1, 2, 2]
lengths = [1,2,3,1]
res = []
start_index = 0
for length in lengths:
res.append(x[start_index:start_index+length])
start_index += length
print(res) # [[2], [1, 2], [0, 1, 2], [2]]
Added this solution to the other answer as it does not need any imported modules.
You can use the following listcomp:
from itertools import accumulate
x = [2, 1, 2, 0, 1, 2, 2]
length = [1, 2, 3, 1]
[x[i - j: i] for i, j in zip(accumulate(length), length)]
# [[2], [1, 2], [0, 1, 2], [2]]

Categories