【问题标题】:Python Generator expression: how to add AND conditions from a loop?Python 生成器表达式:如何从循环中添加 AND 条件?
【发布时间】:2019-07-11 00:35:50
【问题描述】:

具有以下距离矩阵dist

dist = [[[ 0, 0],
[ 5,  0],
[ 1,  0],
[ 1,  1],
[11,  3],
[ 3,  6],
[ 5,  5]],

[[ 5,  0],
[ 0,  0],
[ 6,  0],
[ 4,  1],
[ 6,  3],
[ 2,  6],
[10,  5]],

[[ 1,  0],
[ 6,  0],
[ 0,  0],
[ 2,  1],
[12,  3],
[ 4,  6],
[ 4,  5]],

[[ 1,  1],
[ 4,  1],
[ 2,  1],
[ 0,  0],
[10,  2],
[ 2,  7],
[ 6,  6]],

[[11,  3],
[ 6,  3],
[12,  3],
[10,  2],
[ 0,  0],
[ 8,  9],
[16,  8]],

[[ 3,  6],
[ 2,  6],
[ 4,  6],
[ 2,  7],
[ 8,  9],
[ 0,  0],
[ 8,  1]],

[[ 5,  5],
[10,  5],
[ 4,  5],
[ 6,  6],
[16,  8],
[ 8,  1],
[ 0,  0]]]

我需要使用AND 构建一个generator expression,条件如下:

gexp = (dist[:, :, 0] <= 1) & (dist[:, :, 1] <= 2)

意味着当两个条件都成立时(对于第 0 列和第 1 列),我想要一个值 True,如下所示(我将其打印到列表理解语法):

[array([[ True, False,  True,  True, False, False, False],
       [False,  True, False, False, False, False, False],
       [ True, False,  True, False, False, False, False],
       [ True, False, False,  True, False, False, False],
       [False, False, False, False,  True, False, False],
       [False, False, False, False, False,  True, False],
       [False, False, False, False, False, False,  True]])]

我有这个列列表:

columns = ['weight', 'height']

他们的门槛:

thresholds = {'weight': 1.0, 'height': 1.0}

及其对应的索引:

indexes = {'weight': 0, 'height': 1}

我尝试以这种方式构建我的生成器表达式:

    dynamic_gexpr = [dist[:,:,indexes.get(column)] <= thresholds.get(column) for column in columns]

但我不知道如何在一列和另一列之间添加 AND 条件。上面的表达式似乎更像是 OR 条件来处理它,给出以下输出:

[array([[ True, False,  True,  True, False, False, False],
       [False,  True, False, False, False, False, False],
       [ True, False,  True, False, False, False, False],
       [ True, False, False,  True, False, False, False],
       [False, False, False, False,  True, False, False],
       [False, False, False, False, False,  True, False],
       [False, False, False, False, False, False,  True]]), array([[ True,  True,  True,  True, False, False, False],
       [ True,  True,  True,  True, False, False, False],
       [ True,  True,  True,  True, False, False, False],
       [ True,  True,  True,  True, False, False, False],
       [False, False, False, False,  True, False, False],
       [False, False, False, False, False,  True,  True],
       [False, False, False, False, False,  True,  True]])]

【问题讨论】:

  • 你能分享一个更可复制粘贴的ndarray吗? :-)(一个简单的打印就可以了)
  • 使用numpy,您可以这样做:l2 = np.array(l)l3 = (l2[:, :, 0] &lt;= 1) &amp; (l2[:, :, 1] &lt;= 2)。不确定我是否正确理解了您的问题。
  • @yatu 现在已经被编辑了,我不知道为什么打印时没有逗号。
  • @Jeppe 我需要在运行时使用列、索引和阈值中的值构建这个表达式。

标签: python generator generator-expression


【解决方案1】:

正如@1Z10 在其 cmets 中所建议的,np.reduce 最终将成为您的朋友。

您应该首先构建一个布尔矩阵,其中每个最高级别的行是子数组与其相应阈值的比较。然后只需在该矩阵上使用 np.reducenb.logical_and 即可获得结果,无论涉及多少比较:

dynamic_expr = np.logical_and.reduce(np.array(
    [dist[:, :, indexes[col]] <= thresholds[col]
     for col in columns]))
print(dynamic_expr)

输出是:

[[ True False  True  True False False False]
 [False  True False False False False False]
 [ True False  True False False False False]
 [ True False False  True False False False]
 [False False False False  True False False]
 [False False False False False  True False]
 [False False False False False False  True]]

【讨论】:

    【解决方案2】:

    我使用列表理解来应用构建生成器的条件,反之则感觉不对。无论如何不确定这是否是你想要的。

    x = ([second[0] <= 1 and second[1] <=2 for second in first] for first in dist)
    for y in x:
        print(y)
    

    输出:

    [True, False, True, True, False, False, False]
    [False, True, False, False, False, False, False]
    [True, False, True, False, False, False, False]
    [True, False, False, True, False, False, False]
    [False, False, False, False, True, False, False]
    [False, False, False, False, False, True, False]
    [False, False, False, False, False, False, True]
    

    对于你想要的版本感觉不对

    x = ((second[0] <= 1 and second[1] <=2 for second in first) for first in dist)
    
    for y in x:
        print([next(y),next(y),next(y),next(y),next(y),next(y),next(y)])
    

    输出相同

    现在编写一个单独的函数来进行比较

    def compare(a,b):
        return all([a[i] <= b[i] for i in range(len(a))])
    
    x = ((compare(second, [1,2]) for second in first) for first in dist)
    
    for y in x:
        print([next(y),next(y),next(y),next(y),next(y),next(y),next(y)])
    

    【讨论】:

    • 我可以有 N 个条件,我只会在运行时知道,是否可以在不硬编码 AND 条件或索引以及阈值的情况下以编程方式进行?
    • 添加了另一段代码,我打破了比较位,使其更具程序性......也许这会有所帮助。
    【解决方案3】:

    如果您添加更多列,这应该会扩展。 arrays 将为每个条件保存一个数组。这些中的每一个都通过reduce 处理,而reduce 又会累积所有数组的bitwise_and

    import numpy as np
    from functools import reduce
    columns = ['weight', 'height']
    thresholds = {'weight': 1.0, 'height': 1.0}
    indexes = {'weight': 0, 'height': 1}
    
    l = np.array(dist)
    arrays = [(l[:, :, indexes[column]] <= thresholds[column]) for column in columns]
    l2 = reduce(lambda a, acc : np.bitwise_and(a, acc), arrays)
    print(l2)
    

    输出:

    [[ True False  True  True False False False]
     [False  True False False False False False]
     [ True False  True False False False False]
     [ True False False  True False False False]
     [False False False False  True False False]
     [False False False False False  True False]
     [False False False False False False  True]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-26
      • 2013-03-22
      • 1970-01-01
      • 2013-02-12
      • 2013-04-20
      • 2021-05-09
      相关资源
      最近更新 更多