我在二维列表中有我的值。
a = [[5,2],[7,4],[0,3]]
感谢这个问题的答案 sorting list of lists and getting indices in unsorted list 我设法按递减顺序对它们进行排序,我得到了上一个列表中值的坐标。
from operator import itemgetter
b = [((i, j), v) for i, t in enumerate(a) for j, v in enumerate(t)]
b.sort(key=itemgetter(-1), reverse=True)
print(b)
coords, vals = zip(*b)
print(vals)
print(coords)
输出:
[((1, 0), 7), ((0, 0), 5), ((1, 1), 4), ((2, 1), 3), ((0, 1), 2), ((2, 0), 0)]
(7, 5, 4, 3, 2, 0)
((1, 0), (0, 0), (1, 1), (2, 1), (0, 1), (2, 0))
现在我需要首先计算元素的总累计总和,我使用
执行cumulative_sum = np.cumsum(a)
然后我需要开始对有序元素求和,直到它们达到某个值,即cumulative_sum
的68%。在这种情况下,这意味着要做这个逻辑操作:
1)cumulative_sum = 5 + 2 + 7 + 4 + 0 + 3 = 21
2)68%的cumulative_sum = 14.28
3)然后开始求和:7 + 5 + 4 + ...并选择相关元素,直到它们超过14.28(在这个简化的例子中,这将只选择值7和5)
4)在所选元素中,我需要获取数组a
中的坐标
(在这种情况下,(1,0)
和(0,0)
)
答案 0 :(得分:1)
使用简单的for
循环来迭代b
中的(坐标,值)对,可以轻松完成。诀窍是测试总和是否超出期望的限制之前我们将坐标元组t
添加到selected
中的坐标列表。
from operator import itemgetter
a = [[5,2],[7,4],[0,3]]
b = [((i, j), v) for i, t in enumerate(a) for j, v in enumerate(t)]
b.sort(key=itemgetter(-1), reverse=True)
coords, vals = zip(*b)
total = sum(vals)
lim = int(0.68 * total)
selected = []
s = 0
for t, v in b:
if s + v <= lim:
s += v
selected.append(t)
else:
break
print(s, selected)
<强>输出强>
12 [(1, 0), (0, 0)]
限制计算可以写为
lim = 0.68 * total
但是如果你的数据保证是整数,那么将lim
作为整数也更简洁,因为比较2个整数比将整数与浮点数相比稍微有效一些。当您执行将int与float(包括比较)组合在一起的操作时,必须将它们转换为公共类型以执行操作。
这是备注版本,如评论中所述。它循环遍历vals
中的值,直到达到所需的总和,跟踪vals
中的索引。然后,它使用该索引将已使用的值和相应的坐标元组从b
列表切分为新的selected
列表(与先前版本的selected
列表不同)。 / p>
from operator import itemgetter
a = [[5, 2], [7, 4], [0, 3]]
b = [((i, j), v) for i, t in enumerate(a) for j, v in enumerate(t)]
b.sort(key=itemgetter(-1), reverse=True)
coords, vals = zip(*b)
lim = 0.68 * sum(vals)
s = 0
for i, v in enumerate(vals):
if s + v <= lim:
s += v
else:
break
selected = b[:i]
print(i, selected)
for (i, j), v in selected:
print(i, j, v)
<强>输出强>
2 [((1, 0), 7), ((0, 0), 5)]
1 0 7
0 0 5