【发布时间】:2021-06-24 07:18:03
【问题描述】:
我试图在一个列表中找到最小的 n 个值,它们的位置至少相隔 x,考虑到重复项。例如彼此相距至少 2 的最小 5 个值。
简单的例子:
values = [-9995, -82, -659, -1006, -2009, 2062, -10107, -12, 13]
result: [-10107, -9995, -2009, -659, 13]
更复杂的例子:
values = [-9995, -83, -82, -82, -1006, -2009, 18, 2062, -659 ,-9995, -9995]
例如在上面的列表中:
- -9995 是最小值。
- -9995 再次出现,并且与第一个相距至少 2。剩余的 -9995 将被忽略,因为它与前一个仅相差 1。
- -2009 是第三个最小值
- -1006 不被考虑,因为它与之前的值仅相差 1。所以我们取下一个最小值 -659,因为它与之前的值至少相差 2(假设我们取第一个和最后一个 -9995 并忽略倒数第二个)
- -83 不被考虑,因为它与 -9995 仅相差一个。所以我们取 -82。
- 我们已经达到了 5 个数字,所以我们停止了
result: [-9995, -9995, -2009, -659, -82]
我正在使用的列表有大约 1,000,000 个元素长,我有大约 1000 个列表。我从 pandas DataFrame 生成了这些列表(通过迭代 groupby),所以如果有一个 numpy/pandas 方法来优化这个计算,那将会很有帮助。
假设没有重复,到目前为止的尝试能够生成结果:
def smallest_values(list_of_numbers: list, n_many: int, x_apart: int):
sorted_values = sorted(values)
small_val, small_val_loc = [], []
for val in sorted_values:
if len(small_val) <= n_many:
ind = list_of_numbers.index(val)
within_x = [i for i in range(ind-(x_apart-1), ind+x_apart)]
if not any(i in small_val_loc for i in within_x):
small_val_loc.append(ind)
small_val.append(val)
return small_val
values_simple = [-9995, -82, -659, -1006, -2009, 2062, -10107, -12, 13]
values_complex = [-9995, -83, -82, -82, -1006, -2009, 18, 2062, -659 ,-9995, -9995]
d = 2
n = 5
smallest_values(values_simple, n, d) # [-10107, -9995, -2009, -659, 13] CORRECT
smallest_values(values_complex, n, d) # [-9995, -2009, -659, -82] INCORRECT
【问题讨论】:
-
我不确定您要优化的内容是否明确。考虑
[1, 0, 1, 300, 500, 400]和n=3列表。如果你从零开始,你会得到[0, 300, 400],但如果你从一开始,你会得到[1, 1, 400]。第一个具有最小的数字,但第二个具有最小的总数。哪个是正确答案? -
[0, 300, 400]将是我的问题的正确结果。我不是在寻找最小的总和,我想要至少相隔 x 的最小 n 个数字。谢谢。该算法将从最小的数字开始,并迭代地添加下一个最小的数字,但要遵守它在列表中与之前添加的数字至少相距 x 的约束 -
所以你是说你总是取下一个最小的数字,即使那个选择迫使你以后取更大的数字?所以把
-1加到上面,使n=4——[-1, 100, 1, 0, 1, 300, 500, 400],正确答案是[-1, 0, 300, 400]不是[-1, 1, 1, 400]? -
是的,完全正确
-
在更复杂的示例中取最后一个 -9995 值的逻辑是什么,而不是倒数第二个(这是相同的值,但在列表中较早)?