在Python中增加大量值的最有效方法是什么?

2024-10-03 11:24:29 发布

您现在位置:Python中文网/ 问答频道 /正文

好吧,对不起,如果我的问题有点棘手。我试着用一种比喻的方式来解释,我希望这是令人满意的。在

10 children.
5 boxes.
Each child chooses three boxes.
Each box is opened:
- If it contains something, all children selected this box gets 1 point
- Otherwise, nobody gets a point.

我的问题是关于我用粗体写的。因为在我的代码里,有很多孩子和很多盒子。在

目前,我的工作如下:

children = {"child_1" : 0, ... , "child_10": 0}

gp1 = ["child_3", "child_7", "child_10"] #children who selected the box 1
...
gp5 = ["child_2", "child_5", "child_8", "child_10"]

boxes = [(0,gp1), (0,gp2), (1,gp3), (1,gp4), (0,gp5)]

for box in boxes:
    if box[0] == 1: #something inside
        for child in box[1]:
            children[child] += 1

我主要担心的是for循环,它会给每个孩子分配一个额外的点。因为在我最后的代码中,我有很多孩子,我担心这样做也会减慢程序的速度。在

有没有一种更有效的方法可以让同一组的所有孩子更快地掌握自己的观点?在


Tags: 代码inboxchildfor孩子somethingpoint
3条回答

我能想到的唯一的加速是使用numpy数组和流式处理sum操作。在

children[child] += np.ones(len(children[child]))

您应该对操作进行基准测试,看看这对于您的业务案例是否太慢。在

我会做什么

gpX列表中,不保存“子项的名称”(例如"child_10"),而是保存对子项点数的引用。在

如何做到这一点

利用列表是python中的对象这一事实,您可以:

  1. 将子dict更改为:children = {"child_0": [0], "child_1": [0], ...}等。在
  2. 当您指定给组时,不要指定,而是指定(例如gp1.append(children["child_0"]))。在
  3. 循环应该看起来像:for child in box[1]: child[0]+=1。这更新childrendict

编辑:

为什么更快: 因为您省略了搜索children[child]的部分,这可能会很昂贵。在

这种技术之所以有效,是因为通过以可变类型存储总计,并将这些值附加到组列表中,dict值和每个框的列表值都将指向相同的列表项,更改其中一个将更改另一个。在

  1. 将子级表示为数组中的索引,而不是字符串:

    childrenScores = [0] * 10
    gp1 = [2,6,9] # children who selected box 1
    ...
    gp5 = [1,4,7,9]
    
    boxes = [(0,gp1), (0,gp2), (1,gp3), (1,gp4), (0,gp5)]
    
  2. 然后,可以将childrenScores存储为NumPy数组并使用高级索引:

    ^{pr2}$

    这仍然涉及到某个地方的一个循环,但是这个循环在NumPy的内部很深,这应该可以提供一个有意义的加速。

相关问题 更多 >