我有一个数组:
A = [0,2,5,6]
B = [5,6,8,9]
C = [6,7,8,9]
我想写两个函数,下面是详细信息:
问题1 当我传入上面定义的任何数组时,我按顺序方式得到数字组合(按顺序意义,n + 1)。所以期望的输出是:
ResultA = [[0],[2],[5],[6],[5,6]]
ResultB = [[5],[6],[8],[9],[5,6],[8,9]]
ResultC = [[6],[7],[8],[9],[6,7],[7,8],[8,9],[6,7,8],[7,8,9],[6,7,8,9]]
以下是我尝试的内容:
sorted_ids = sorted(number_collection)
combinations = [sorted_ids[j: j + i] for i in range(1, len(sorted_ids)) for j in range(len(sorted_ids) - i + 1)]
问题是它适用于数组C
,但与其他数组的效果不佳。
问题2
problem 1
的结果是此问题的输入。问题是我想要存在于数字的唯一元素上的组合。 (我不确定我能用正确的方法解释它),下面是所需的输出:
FinalResultA = [[0],[2],[5,6]]
FinalResultB = [[5,6],[8,9]]
FinalResultC = [[6,7,8,9]]
我可以使用哪种方法(以性能为导向)帮助吗?
答案 0 :(得分:1)
这是一种相当有效的方法,虽然它确实需要O(N)辅助空间,但如果运行次数很少那么它不应该是重要的:
from itertools import groupby
def ngrams(seq):
stop = len(seq)+1
for n in range(2, stop):
for i in range(stop - n):
yield seq[i:i+n]
def get_combos(seq):
runs = []
for _, g in groupby(enumerate(seq), lambda x:x[1]-x[0]):
run = [a for _, a in g]
for x in run:
yield [x]
if len(run) > 1:
runs.append(run)
for run in reversed(runs):
yield from ngrams(run)
注意,这使用this classic approach对连续的整数进行分组。它迭代连续整数组,"运行",并产生任何单个整数作为单元素列表。如果运行时间长于1,我将其添加到运行列表中。最后,你反过来迭代运行列表,产生" n-gram",从订单2到订单len(运行)。
行动中:
>>> A = [0,2,5,6]
>>> B = [5,6,8,9]
>>> C = [6,7,8,9]
>>> list(get_combos(A))
[[0], [2], [5], [6], [5, 6]]
>>> list(get_combos(B))
[[5], [6], [8], [9], [8, 9], [5, 6]]
>>> list(get_combos(C))
[[6], [7], [8], [9], [6, 7], [7, 8], [8, 9], [6, 7, 8], [7, 8, 9], [6, 7, 8, 9]]
get_combos
假设输入已排序。
>>> D = [6,7,9,12,13,14,20,21,30]
这将产生:
>>> list(get_combos(D))
[[6], [7], [9], [12], [13], [14], [20], [21], [30], [20, 21], [12, 13], [13, 14], [12, 13, 14], [6, 7]]
I.E。,3序列在后续运行的2个序列产生之前开始。如果希望在n + 1个len序列之前产生所有n-len序列,请使用以下方法:
from itertools import groupby
def ngrams(seq, max_len):
curr = seq
for n in range(1, max_len + 1):
nxt = []
for run in curr:
run_len = len(run)
if run_len > n:
nxt.append(run)
for i in range(run_len + 1 - n):
yield run[i:i+n]
curr = nxt
def _sub_index(t):
return t[1] - t[0]
def get_consecutive_runs(seq):
grouped = groupby(enumerate(seq), _sub_index)
for _, g in grouped:
yield [a for _, a in g]
def get_combos(seq):
runs = list(get_consecutive_runs(seq))
max_len = max(map(len, runs))
yield from ngrams(runs, max_len)
得到以下结果:
>>> list(get_combos(D))
[[6], [7], [9], [12], [13], [14], [20], [21], [30], [6, 7], [12, 13], [13, 14], [20, 21], [12, 13, 14]]
答案 1 :(得分:0)
这是您在一个没有任何外部库的函数中的两个解决方案:
A = [0,2,5,6]
B = [5,6,8,9]
C= [6,7,8,9]
def finding_sequence(list_1):
sub_list = []
for j, i in enumerate(list_1):
try:
if list_1[j] - list_1[j - 1] == 1:
sub_list.append((list_1[j - 1], list_1[j]))
else:
sub_list.append('_pos')
except IndexError:
pass
sub_final_result = []
check_result=[]
if '_pos' not in sub_list[1:]:
for i in sub_list[1:]:
for k in i:
if k not in sub_final_result:
sub_final_result.append(k)
check_result.append(k)
else:
for i in sub_list:
if i != '_pos':
sub_final_result.append(i)
for i1 in i:
check_result.append(i1)
for i1 in list_1:
if i1 not in check_result:
sub_final_result.append([i1])
return sub_final_result
测试用例:
print(finding_sequence(A))
输出:
[(5, 6), [0], [2]]
第二
print(finding_sequence(B))
输出:
[(5, 6), (8, 9)]
P.S:一个请求:如果我的回答对您有帮助,请不要接受,只需使用它。