2015-10-31 199 views
3

我有一个布尔数组,现在我想交换这些条目的数字。遍历数组

False => 0 
True => 1 

我写了两段不同的代码,我想知道哪一段更好,为什么。这不是关于实际解决问题,而是关于学习。

arr = [[True,False],[False,True],[True,True]] 

for i,row in enumerate(arr): 
    for j,entry in enumerate(row): 
     if entry: 
      arr[i][j] = 1 
     else: 
      arr[i][j] = 0 
print(arr) 

而第二种方法:

arr = [[True,False],[False,True],[True,True]] 

for i in range(len(arr)): 
    for j in range(len(arr[i])): 
     if arr[i][j]: 
      arr[i][j] = 1 
     else: 
      arr[i][j] = 0  
print(arr) 

,我读了有办法与进口itertools或类似做到这一点。如果可以用“板载工具”来完成,我真的不喜欢导入东西,但是我应该用它来解决这个问题吗?

+2

绝对选项A;遍历范围(len(...))'不是pythonic。 – jonrsharpe

+0

非常感谢。那是我正在寻找的答案! – Swift

回答

9

让我们来定义你的数组:

>>> arr = [[True,False],[False,True],[True,True]] 

现在,让我们转换布尔整数:

>>> [[int(i) for i in row] for row in arr] 
[[1, 0], [0, 1], [1, 1]] 

另外,如果我们想更灵活的什么被取代的,我们可以用一个三元语句:

>>> [[1 if i else 0 for i in row] for row in arr] 
[[1, 0], [0, 1], [1, 1]] 
+1

打败我,更优雅,我只是做了'[(lambda x:[int(y)for y in x])(i)因为我在foo]' - 我不知道为什么我的大脑关机这么辛苦,我不只是做你做的:)星期五结束的一天必须是 –

+0

也许'int(bool(i))'而不是三元? – ekhumoro

+1

John1024。非常感谢您在最后部分加入。因为稍后我可能想使用一些其他符号而不是1和0:D – Swift

3

如果你想留在一个for循环(例如因为你想改变现有的数组而不是创建一个新的数组),你应该简化代码。

我想先通过删除索引(也没有必要为它,因为它修改的行不是一个嵌套的数组更简单)简化了外部循环:

for row in arr: 
    for j, entry in enumerate(row): 
     if entry: 
      row[j] = 1 
     else: 
      row[j] = 0 

这类简单的if语句可以通常使用if表达式进行简化:

row[j] = 1 if entry else 0 

但在这种情况下,我们可以做得更好。 bool是的一个子类int(即所有bool的是int‘峰),和TrueFalse被定义为恰好10分别 - 如果您向下滚动到PEP 285(https://www.python.org/dev/peps/pep-0285/)的说明书中部分你’我们会发现这种等价不是偶然的,而是通过设计非常重要。

因此,我们可以使用int构造抢底层整数值[*],因为int(True) == 1int(False) == 0,如果 - 表达式可以简化为:

row[j] = int(entry) 

[*]技术上这是一个明确的上溯造型到一个基类,而不是转换构造..

简化代码:

for row in arr: 
    for j, entry in enumerate(row): 
     row[j] = int(entry)