问题
I am trying to create a function that takes a list as input and returns all possible selections of a particular number of elements from a list without using the inbuilt combination()
function in itertools
.
For example, if we pass the list [1,2,3,4]
and the number 3 to such a function, the function should return [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
I have created a version of this function if the number of elements to be selected is 3 but I do not know how to deal with a generic number of nested for loops and comparisons.
My code:
sample_set = [1,2,3,4]
def selections(input_set, number):
if number == 3:
#frozensets are used here so a set of sets can be generated and so that frozensets containing the same elements in different order can be removed when we apply set()
frozenset_list = [frozenset((i, j, k)) for i in input_set for j in input_set for k in input_set if i != j !=k !=i ]
unique_frozenset_list = set(frozenset_list) #removing identical frozensets
return [list(i) for i in unique_frozenset_list] #converting all frozensets to lists
print(selections(sample_set, 3))
回答1:
I got a combination of indexes to remove, so if you wanted 3 items from a list of 5, there would be combinations of two indexes I could remove e.g (2,5)
I threw in some conditions to make sure there were no duplicates, and that the length of list would be to the max which would be nCr, nCr
is a maths formulae.
Then I would just use these combinations to make list that didn't include the indexes from these combinations, and added to the master list final_list
import random
import math
def go(sample_set,num):
new_list = []
n = len(sample_set)
r = len(sample_set) - num
nCr = (math.factorial(n) / math.factorial(r) / math.factorial(n - r))
while len(new_list) < int(nCr):
co = [random.randint(0,len(sample_set)-1) for count in range(r)]
if len(co) == len(set(co)) and co not in new_list:
new_list.append(co)
final_list = []
for x in new_list:
combination = [q for q in sample_set if sample_set.index(q) not in x]
final_list.append(combination)
return sorted(final_list) # sorted is optional
print(go([1, 2, 3, 4],3))
>>> [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
print(go([1, 2, 3, 4, 5],3))
>>> [[1, 2, 3], [1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 4, 5], [1, 4, 5], [2, 3, 4], [2, 3, 4], [2, 3, 5], [3, 4, 5]]
I just realised I can do it forwards instead of backwards, as in just get all possible combinations of 3 indexes (or whatever number is given) and print a list based on that.
def go(sample_set,num):
new_list = []
n = len(sample_set)
nCr = (math.factorial(n) / math.factorial(num) / math.factorial(n - num))
while len(new_list) < int(nCr):
co = [random.randint(0,len(sample_set)-1) for count in range(num)]
if len(co) == len(set(co)) and co not in new_list:
new_list.append(co)
final_list = []
for x in new_list:
combination = [q for q in sample_set if sample_set.index(q) in x]
final_list.append(combination)
return sorted(final_list) # sorted is optional
print(go([1, 2, 3, 4],3))
来源:https://stackoverflow.com/questions/64881363/creating-selections-from-the-elements-of-a-list-using-a-general-number-of-nested