Python - 选择总计达2D列表中累计和的68%的元素

时间:2016-11-01 12:19:03

标签: python sorting

我在二维列表中有我的值。

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)

1 个答案:

答案 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