【问题标题】:Filter list values with a default fall-back option使用默认后备选项过滤列表值
【发布时间】:2018-07-03 13:55:19
【问题描述】:

给定 2 个数字列表:

real_solutions_sols1 =  [-53.2909210236, -8.31658000998, 1.87689837129, 1.4]
real_solutions_sols2 =  [-21.1439685227, -19.2]

我希望使用相同的代码来重写列表,以便它们包含介于 0.14.0 之间的数字:

real_solutions_sols1 =  [ 1.87689837129, 1.4]

对于第二个列表,这是不可能的,所以我希望代码返回完整的列表:

real_solutions_sols2 =  [-21.1439685227, -19.2]

以下代码适用于real_solutions_sols2

real_roots_zero_to_four = []
for i in real_solutions_sols2:
   if (i >= 0.1) and (i <= 4.0):
      real_roots_zero_to_four.append(i)
   else:
     real_roots_zero_to_four = real_solutions_sols2

print 'real_roots_zero_to_four = ', real_roots_zero_to_four

if 条件不满足,所以我们跳转到else 语句。

real_roots_zero_to_four = [-21.14396852, -19.2]

但是,对于第一个列表,它会无限循环:

real_roots_zero_to_four = []
for i in real_solutions_sols1:
   if (i >= 0.1) and (i <= 4.0):
      real_roots_zero_to_four.append(i)
   else:
     real_roots_zero_to_four = real_solutions_sols1

print 'real_roots_zero_to_four = ', real_roots_zero_to_four

我不知道为什么会这样

【问题讨论】:

  • @Nick A 感谢您的评论。以我的拙见,我认为这些链接不是重复的,因为如帖子中所述,将&amp;&amp; 替换为and 后,问题仍然存在。正如 Ev 正确指出的那样。 Kounis,这是一个逻辑问题,已经在帖子标题中进行了编辑。
  • 那很好,它只是一个可能的重复而不是明确的,因为我删除了评论,你似乎得到了一个很好的答案,所以没有伤害:)

标签: python list for-loop if-statement append


【解决方案1】:

您可以使用以下成语\模式:

my_list = [x for x in my_list if 0.1 <= x <= 4] or my_list

这里发生的情况是,我们正在利用逻辑 or 的工作方式与 Python 中列表的布尔特性相结合。

具体来说,假设我们有:

<exp 1> or <exp 2>

Python 解释器将首先评估or左侧 上的任何内容的真实性。如果该检查返回True,则返回&lt;exp 1&gt; True)。否则,&lt;exp 2&gt; 将被返回,而不管其未检查的 truthiness 值如何。利用bool([]) 返回False 的事实,我们可以确定如果我们的列表推导返回一个空列表,则or 的右侧将被返回(原始列表my_list)。

因此,我们正在做的是优雅地说以下内容:

给定my_list,获取其所有满足if 条件的元素,除非没有任何元素,在这种情况下只返回原始元素。


您的代码中的问题是使用了&amp;,这在 Python 中表示and。逻辑 ANDand 所以相反,你应该这样做 if (i &gt;= 0.1) and (i &lt;= 4.0):

最后,请注意,在 Python 中,像 i &gt;= 0.1 and i &lt;= 4.0 这样的表达式可以“压缩”成 0.1 &lt;= i &lt;= 4.0(就像您在 Math 类中编写的那样)。

【讨论】:

  • 是的,绝对是我的最爱。
  • 您可能需要澄清一下在 python 中0.1 &lt; x &lt; 4 是一个有效的语句,以及&amp;and 是不是同一件事
  • @Ev. Kounis 谢谢你的回答。您的列表理解方法非常优雅,我真的很感激。但是,我试图理解为什么那些forif 循环不起作用:请注意,如果我用and 替换&amp;,我仍然会得到一个无限循环。你能帮我理解上面代码中的问题在哪里吗?再次感谢所有的努力
  • @DavidC。因为每次遇到不符合条件的数字时,您都会覆盖real_roots_zero_to_four。不知道如何向您解释这一点。试着跟随代码,一次又一次地迭代,你会亲眼看到的。
  • @DavidC.Well,不是在这种情况下,而是无论如何。 Here you go
【解决方案2】:

我只是要指出无限 for 循环的原因,因为当我们分配 real_roots_zero_to_four = real_solutions_sols1

您正在执行浅拷贝,这意味着我们指的是变量的同一个副本,即它们是指向同一块内存的指针

然后当你这样做时

if (i >= 0.1) & (i <= 4.0):
     real_roots_zero_to_four.append(i)

您正在附加到real_roots_zero_to_fourreal_solutions_sols1

然后我们在forloop中的相同位置循环

for i in real_solutions_sols1:

因为它们指向相同的东西,然后我们检查相同的东西 元素并无限添加,直到系统崩溃

为了在另一个列表上运行附加,我们必须做一个深拷贝 可以使用

创建
real_roots_zero_to_four =list( real_solutions_sols1 )

那么就不会再有无限的forloops了

【讨论】:

  • 感谢您的评论
【解决方案3】:

@Ev 给出的答案。 Kounis 无疑是您问题的最佳解决方案。但是我认为看看你的代码为什么不起作用很有趣。罪魁祸首在这里:

real_roots_zero_to_four = real_solutions_sols1

当满足else 语句时,执行上述行并将real_solutions_sols1引用 复制real_roots_zero_to_four 中。从现在开始,所有附加到real_roots_zero_to_four 的值也将附加到real_solutions_sols1

从这里开始,无限循环。

【讨论】:

  • 感谢您的解释
【解决方案4】:

使用列表理解:

result = [x for x in [-53.2909210236, -8.31658000998, 1.87689837129, 1.4] if x >= 0.1 and x <=4.0]
print(result)
# [1.87689837129, 1.4]

顺便说一句,你为什么使用&amp; 作为逻辑AND?这是用 Python 编写的:

if i >= 0.1 and i <= 4.0:

【讨论】:

  • 抱歉,我确实看到这(可能)解决了 OP 代码中的问题,但您可能想改写并解释 why 使用 &amp; 不会引发语法错误,但仍然给出错误的答案
  • 正确,我已经为实际问题添加了解决方案。