我需要的东西与询问的here类似,但反之则更多:
给出一个数字列表(来自上述问题的示例):[1、6、9、100、102、105、109、134、139]我不想说最大差距(在该示例中为10)但是我想要几个小组。
例如 3组:1、6、9 / 100、102、105、109 / 134、139 2组:1、6、9 / 100、102、105、109、134、139 ...
这应该是相对的,因为我的数字非常非常不同: [0.1,0.2,1,4,100,110] => 3组应得出0.1、0.2 / 1、4 / 100、110
尽管0.2和1在绝对值上分别比1和5(0.8对3)更近,而0.2与1(5倍)比0.1(2x)更远。
我希望我能以某种方式弄清楚我想要实现的目标...
答案 0 :(得分:0)
import sys
# Sorted numbers.
xs = [0.1, 0.2, 1, 4, 100, 110]
xs.sort()
# Reverse-sorted (RATIO, INDEX) tuples.
tups = sorted(
(
(xs[i] / xs[i - 1] if i else 0, i)
for i, x in enumerate(xs)
),
reverse = True,
)
# Indexes of the boundaries having the largest ratios.
n_groups = int(sys.argv[1])
boundaries = sorted(tup[1] for tup in tups[0 : n_groups - 1])
boundaries.append(None)
# Create the groups, based on those boundaries.
groups = []
i = 0
for j in boundaries:
groups.append(xs[i:j])
i = j
# Check.
for g in groups:
print(g)
示例输出:
# n_groups = 1
[0.1, 0.2, 1, 4, 100, 110]
# n_groups = 2
[0.1, 0.2, 1, 4]
[100, 110]
# n_groups = 3
[0.1, 0.2]
[1, 4]
[100, 110]
# n_groups = 4
[0.1, 0.2]
[1]
[4]
[100, 110]
# n_groups = 5
[0.1]
[0.2]
[1]
[4]
[100, 110]
答案 1 :(得分:0)
如果数字列表不是巨大,则我将首先计算数字与其先例之间的每个比率,然后选择最大的拆分。
例如:
def split_numbers_list(numbers_list, n_groups):
# If the number of groups is 1 or less, the whole list the only group
if n_groups <= 1:
return [numbers_list]
n_splits = min(len(numbers_list), n_groups) # Can't have more groups than elements
# Now we calculate the ratios and store them in (index, ratio) tuples
ratios = [
(i, numbers_list[i + 1] / numbers_list[i]) for i in range(len(numbers_list) - 1)
]
sorted_ratios = sorted(ratios, key=lambda r: r[1], reverse=True)
# `chosen_splits` stores the boundaries of each group
chosen_splits = (
[0]
+ sorted([r[0] + 1 for r in sorted_ratios[: n_splits - 1]])
+ [len(numbers_list)]
)
return [
numbers_list[chosen_splits[i] : chosen_splits[i + 1]]
for i in range(len(chosen_splits) - 1)
]
但是请注意numbers_list
的含义:它必须是严格正数数字的排序列表,否则此功能将不起作用。
一些例子:
>>> my_list = [1, 2, 3, 4, 5, 100, 101, 103, 504, 2301]
>>> split_numbers_list(my_list, 5)
[[1], [2, 3, 4, 5], [100, 101, 103], [504], [2301]]
>>> split_numbers_list(my_list, 3)
[[1, 2, 3, 4, 5], [100, 101, 103], [504, 2301]]