首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我不能从列表中删除所需的元素

为什么我不能从列表中删除所需的元素
EN

Stack Overflow用户
提问于 2021-02-11 22:54:57
回答 3查看 88关注 0票数 3

我正在编写一段代码,并且必须对给定的列表进行排序。

代码语言:javascript
运行
复制
prices = [5, 11, 3, 50, 60, 90]
k = 2
all_posible_sales = []
i=0
for buy in prices[i:len(prices)]:
    for sell in prices[i:len(prices)]:
        a = tuple((buy, sell))
        all_posible_sales.append(a)
    i += 1

for data in all_posible_sales:
    if data[1] - data[0] < 0 or data[1] - data[0] == 0:
        all_posible_sales.remove(data)
print(all_posible_sales)

这段代码连接了所有可能的销售(两个嵌套的for循环),并删除了差为负值的变量(最终的for循环)。

当我检查输出时,我发现一件非常令人不愉快的事情:元组(11, 3)在那里,它一定不在那里,这符合我的逻辑。

data1 -数据<0\3-11<0(真)

这个价值有什么问题,我做错什么了吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-02-11 23:02:18

与将元素添加到列表中然后删除不同,您只需将有效元素添加到列表中,方法如下:

代码语言:javascript
运行
复制
prices = [5, 11, 3, 50, 60, 90]
k = 2
all_posible_sales = []
i=0
for buy in prices[i:len(prices)]:
    for sell in prices[i:len(prices)]:
        if sell - buy > 0:
            a = tuple((buy, sell))
            all_posible_sales.append(a)

还请阅读此,以了解如何为未来的应用程序成功地从列表中删除项。

票数 0
EN

Stack Overflow用户

发布于 2021-02-12 01:49:58

引言

这两个发布的答案实际上都没有解决代码中的问题。问题是,您没有从正在迭代转发的列表中删除项。要开始了解原因,请打印实际被删除的元组:

代码语言:javascript
运行
复制
(5, 5)
(5, 3)
(11, 11)
(3, 3)
(50, 50)
(60, 60)
(90, 90)

注意,(11, 3)从未被检查过。这是因为列表迭代器基于索引工作。每次移除项时,以下所有项都会移回一个项,但是迭代器会继续递增。下面是起始all_possible_sales列表中的一个示例:

  1. 从索引0处的迭代器开始:[(5,5),(5,11),(5,3),.^ i=0
  2. 放弃该项目,因为5 <= 5。注意数据向后移动,但是迭代器保持在列表中相同的位置:[(5,11),(5,3),(5,50),.^ i=0
  3. 循环下一次迭代的步骤:[(5,11),(5,3),(5,50),.^ i=1

希望您能够看到如何跳过(5, 11),以及之后的许多元素(实际上,几乎每一个其他元素)。

解决方案

现在让我们来看看一些解决方案。我从一些几乎是表面上的改变开始,工作到彻底修改您的代码,甚至比其他答案所推荐的更多。

反向迭代

当您向后迭代一个列表时,删除不会影响您没有遍历的索引。列表有一个反向迭代器,这意味着调用reversed不会复制任何东西,因此时间和内存都很便宜。

因此,最简单的解决方案是将第二个循环替换为:

代码语言:javascript
运行
复制
for data in reversed(all_posible_sales):

复制输入

如果创建输入列表的副本,其元素将指向相同的对象,但从原始列表中删除项不会影响迭代器对副本的影响。这比颠倒原始列表要昂贵得多,因为它实际上分配了第二个列表。

该解决方案至少可以用三种不同的方式编写:

  1. for data in list(all_posible_sales):
  2. for data in all_posible_sales.copy():
  3. for data in all_posible_sales[:]:

不包括不必要的元素

正如其他答案所示,最好的方法是排除不属于的元素,而不是稍后删除它们。这种方法的部分答案是调整循环,这样就不会创建表单(buy, buy)的元组

代码语言:javascript
运行
复制
for ibuy in range(len(prices) - 1):
    buy = prices[ibuy]
    for isell in range(ibuy + 1, len(prices)):
        sell = prices[isell]

条件内循环

从列表中排除项目的最简单方法是,从一开始就不包括它们:

代码语言:javascript
运行
复制
for ibuy in range(len(prices) - 1):
    buy = prices[ibuy]
    for isell in range(ibuy + 1, len(prices)):
        sell = prices[isell]
        if buy < sell:
            all_posible_sales.append((buy, sell))
print(all_posible_sales)

清单理解

任何嵌套的for循环,只要有条件和列表append,都可以作为列表理解来更有效地(如果不是更清楚地)编写。在这种情况下,它将涉及更多的索引:

代码语言:javascript
运行
复制
all_posible_sales = [(prices[ibuy], prices[isell]) for ibuy in range(len(prices) - 1) for isell in range(ibuy + 1, len(prices)) if prices[ibuy] < prices[isell]]

请注意,这就像按照与以前完全相同的顺序编写循环和条件,但都在一行上,没有冒号。唯一的区别是append调用的内容在开头。

Numpy

像这样有数字的东西非常适合于矮胖。如果您正在进行任何类型的数字处理,那么您几乎不可避免地会导入numpyscipypandas的一部分。您的代码将更干净和更快。

如果将prices转换为numpy数组,则可以在循环结束时使用函数np.triu_indices查找相同的对。然后,您可以将所选内容连接到一个买卖价格的Nx2数组中:

代码语言:javascript
运行
复制
import numpy as np

prices = np.array(prices)
ibuy, isell = np.triu_indices(len(prices), k=1)
all_possible_sales = np.stack((prices[ibuy], prices[isell]), axis=-1)[prices[ibuy] < prices[isell]]

备注

  • 您不需要在索引中显式地声明len(prices)prices[i:]将接受所有元素到末尾,而prices[i:-1]将接受所有元素,直到结束时有一个元素,等等。
  • 表达式data[1] - data[0] < 0 or data[1] - data[0] == 0可以以data[1] - data[0] <= 0的形式编写得简洁得多。更好的(我认为,更直截了当地说)是比较data[1] <= data[0]
  • 表达式tuple((buy, sell))完全等同于(buy, sell)。我觉得后者读起来不那么令人困惑。
  • 表达式for sell in prices[i:len(prices)]:在外部循环的每次迭代中生成一个prices片段的完整副本。迭代range对象并将其索引到prices中可能要便宜得多。
票数 7
EN

Stack Overflow用户

发布于 2021-02-11 23:00:39

在迭代列表时,不要从列表中删除,除非您知道自己在做什么。使用列表理解代替:

代码语言:javascript
运行
复制
all_posible_sales = [s for s in all_posible_sales if s[0] < s[1]]
print(all_posible_sales)
# [(5, 11), (5, 50), (5, 60), (5, 90), (11, 50), (11, 60), (11, 90), (3, 50), (3, 60), (3, 90), (50, 60), (50, 90), (60, 90)]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66164174

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档