Reputation: 360
I have an array of bools and now I want to swap those entries for numbers.
False => 0
True => 1
I have written two different pieces of code and I would like to know, which one is better and why. This is not so much about actually solving the problem, as about learning.
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)
And the second approach:
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)
I read that there are ways to do this with importing itertools
or similar. I am really not a fan of importing things if it can be done with “on-board tools”, but should I rather be using them for this problem?
Upvotes: 8
Views: 52460
Reputation: 27351
If you want to stay with a for-loop (e.g. because you want to mutate the existing array instead of creating a new one), you should simplify the code.
I would first simplify the outer loop by removing the indexing (there is no need for it since it's even easier to modify a row than a nested array):
for row in arr:
for j, entry in enumerate(row):
if entry:
row[j] = 1
else:
row[j] = 0
these kinds of simple if statement can often be simplified by using an if expression:
row[j] = 1 if entry else 0
but in this case we can do even better. bool
is a subclass of int
(ie. all bool
's are int
's), and True
and False
are defined to be exactly 1
and 0
respectively -- if you scroll down to the specification section of PEP 285 (https://www.python.org/dev/peps/pep-0285/) you'll see that that equivalence is not accidental but very much by design.
We can therefore use the int
constructor to grab the underlying integer values[*], since int(True) == 1
and int(False) == 0
, the if-expression can be simplified to:
row[j] = int(entry)
[*] technically this is an explicit upcast to a base class, and not a conversion constructor..
The simplified code:
for row in arr:
for j, entry in enumerate(row):
row[j] = int(entry)
Upvotes: 4
Reputation: 113934
Let's define your array:
>>> arr = [[True,False],[False,True],[True,True]]
Now, let's convert the booleans to integer:
>>> [[int(i) for i in row] for row in arr]
[[1, 0], [0, 1], [1, 1]]
Alternatively, if we want to be more flexible about what gets substituted in, we can use a ternary statement:
>>> [[1 if i else 0 for i in row] for row in arr]
[[1, 0], [0, 1], [1, 1]]
Upvotes: 12