【问题标题】:element wise checking of nested list嵌套列表的元素明智检查
【发布时间】:2019-04-25 18:33:21
【问题描述】:

逐元素检查嵌套列表的多个条件,如果条件不满足或满足,则返回 0 或 1。

我要检查一下

至少 14 个

不能等于= 19

如果元素以 4 或 9 结尾

例如年龄数组

[[22, 13, 31, 13],
 [17, 14, 24, 22]]

将输出数组作为

[[0, 0, 0, 0], 
 [0, 1, 1, 0]]

我尝试将列表展平,然后检查每个条件,但它不起作用。

flat_list = [item for sublist in age for item in sublist]
x=14
[not x for x in flat_list]

【问题讨论】:

  • at least 14 != 19 是什么意思?
  • 您是否尝试检查这些值是否不等于x
  • 另外,not 14 将返回 False,因为 14 的行为类似于 True

标签: python nested-lists elementwise-operations


【解决方案1】:

有一个更快的 numpy 解决方案:

((arr >= 14) & (arr != 19) & ((arr%10 == 4) | (arr%10==9))).astype(int)

代码

import numpy as np

arr = np.array([[22, 13, 31, 13],
                [17, 14, 24, 22]])

print(((arr >= 14) & (arr != 19) & ((arr%10 == 4) | (arr%10==9))).astype(int))

# [[0 0 0 0]
#  [0 1 1 0]]

【讨论】:

  • 谢谢!这就是答案: print (((arr%10 == 4) | (arr%10 == 9) & (arr >= 14) & (arr != 19)).astype(int))
  • @C.Nivs,这个要求对我来说有点不清楚,谢谢。重铸是指转换为 1 和 0 吗?这些逻辑运算产生了一个真假数组,它们只不过类似于 1 和 0。 (注意 boolean 是 int 的子类。)
  • @Austin 是的,这就是问题所在,但我在您回复之前不久在文档中发现了这一点。不过谢谢!
  • @Austin 我对我的代码进行了一些分析,出于好奇,也分析了numpy 实现,结果发现numpy 比map 实现慢。 python -m timeit -s 'import numpy as np; arr = np.array([[22, 13, 31, 13],[17, 14, 24, 22]])' '((arr >= 14) & (arr != 19) & ((arr%10 == 4) | (arr%10==9))).astype(int)' 100000 loops, best of 3: 6.53 usec per loop。我无法完全理解那个,因为我想象numpy 会将map 实现从水中吹走(这是python 3.6,numpy 1.16.2)
【解决方案2】:

你可以用这样的列表推导来做到这一点:

somelist = [[22, 13, 31, 13],
 [17, 14, 24, 22]]

result = [[1 if (x%10==4 or x%10==9) and (x>=14 and x!=19) else 0 for x in sublist] for sublist in somelist]

result
[[0, 0, 0, 0], [0, 1, 1, 0]]

x%10 将获取每个数字的最后一位数字,以便直接比较。通过将这两个条件分组,您可以更合乎逻辑地列出您想要做的事情,尽管这对于列表理解来说有点混乱。

更好的方法(可能会牺牲速度)可能是使用map

def check_num(num):
    value_check = num >= 14 and num != 19
    last_num_check = num % 10 == 4 or num % 10 == 9
    return int(value_check and last_num_check)

somelist = [[22, 13, 31, 13],
 [17, 14, 24, 22]]

result = [[x for x in map(check_num, sublist)] for sublist in somelist]

result
[[0, 0, 0, 0], [0, 1, 1, 0]]

时序操作的区别:

列表理解

python -m timeit -s 'somelist = [[22, 13, 31, 13], [17, 14, 24, 22]]' '[[1 if (x%10==4 or x%10==9) and (x>=14 and x!=19) else 0 for x in sublist] for sublist in somelist]'
1000000 loops, best of 3: 1.35 usec per loop

地图

python -m timeit -s 'from somefunc import check_num; somelist = [[22, 13, 31, 13], [17, 14, 24, 22]]' '[[x for x in map(check_num, sublist)] for sublist in somelist]'
100000 loops, best of 3: 3.37 usec per loop

【讨论】:

  • 谢谢!这有效: [[1 if x%10==4 or x%10==9 and x>=14 and x!=19 else 0 for x in sublist] for sublist in X] 但是它没有通过,因为解决方案编译速度不够快......它必须比某个阈值快
  • @JuliaDills 那么我肯定会看看@Austin 的解决方案,因为numpy's 矢量化操作可能会更快
【解决方案3】:

C.Nvis 在列表理解方面有一个很好的答案。你也可以使用嵌套的 for 循环来解决这个问题

def is_valid(x):
    return (x == 14) or (x%10 == 4) or (x%10 == 9)

out = []

for sublist in matrix:
    out_sublist = []
    for i in sublist:
        if (is_valid(i)):
            out_sublist.append(1)
        else:
            out_sublist.append(0)
    out.append(out_sublist)

print(out)

这些答案实际上是相同的算法。

【讨论】:

    【解决方案4】:

    就您的示例而言,它可以通过一些映射来完成。

    验证最后一位数字是否等于数字的方法是对数字应用模 10。

    my_list = [[22, 13, 31, 13],[17, 14, 24, 22]]
    
    result_list = []
    for sublist in my_list:
        result_list.append(list(map(lambda x: 1 if x % 10 == 4 and x >= 14 and x != 19 else 0, sublist)))
    
    print(result_list)
    

    将产生:

    [[0, 0, 0, 0], [0, 1, 1, 0]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-09
      • 2022-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多