tags:

views:

234

answers:

6

Hello, I'm trying to take a binary number in string form, and flip the 1's and 0's, that is, change all of the 1's in the string to 0's, and all of the 0's to 1's. I'm new to Python, and have been wracking my brain for several hours now trying to figure it out.

Thanks for any help you can offer.

+12  A: 
>>> ''.join('1' if x == '0' else '0' for x in '1000110')
'0111001'

The a for b in c pattern is a generator expression, which produces a series of items based on a different series. In this case, the original series is the characters (since you can iterate over strings in Python, which gives you the characters that make up that string), and the new series is a set of characters with the 0's and 1's flipped.

'1' if x == '0' else '0' is pretty straightforward - it gives us whichever of 1 or 0 isn't x. We do this for each such x in the original set of characters, and then join() them all together (with an empty string '', a.k.a. nothing, in between each item), thus giving us a final string which is all of the opposite characters from the original, combined.

Amber
Clever. I like the comprehension. +1
Xorlev
To make it too clever by half, you may elect to replace the `if` expression with `'01'[x=='0']`. I still prefer your answer, but thought I would mention it.
Muhammad Alkarouri
A: 

http://docs.python.org/library/string.html#string.replace

Replace all the 1's with 2's, then replace the 0's with 1's, finally replacing the 2's with 0's.

"10011".replace("1", "2").replace("0", "1").replace("2", "0")
yodaj007
A: 

Amber's answer, while superior, possibly isn't the most clear, so here's a super basic iterative example:

b_string = "1100101"
ib_string = ""

for bit in b_string:
  if bit == "1":
    ib_string += "0"
  else:
    ib_string += "1"

print ib_string

This can be done in much better ways...replacements, comprehensions, but this is an example.

I would learn from the other answers in this question once you understand the basis of this one. This method is slow and painful. For the best performance, as Muhammad Alkarouri pointed out, the string.translate/maketrans combo is the way to go. Right behind it is the comprehension. My code is the slowest by a significant margin.

Xorlev
I'd like to avoid encouraging people to use `+=` for strings, as opposed to `join()` - not only is `join()` more Pythonic, but it's also the more efficient method for general usage. It's a good habit to instill early.
Amber
After a while working with Python one tends to find list comprehensions as clear or clearer than `for` loops.
Robert Rossney
I personally prefer the comprehension, it makes more sense to me.
Xorlev
Generally, don't speculate in timing. In this case, `timeit ''.join('1' if x == '0' else '0' for x in b_string)` gives 5.3 microseconds on my machine, while `timeit b_string.translate(maketrans("10", "01"))` gives 979 _nanoseconds_.
Muhammad Alkarouri
A: 

Along the lines of Amber, but using ASCII arithmetic (for no particular reason). This obviously isn't meant for production code.

''.join(chr(97 - ord(c)) for c in my_bit_string)

48 and 49 are the ASCII (and Unicode) values for '0' and '1' respectively. ord gives you the numeric value for a character, while chr does the reverse.

Matthew Flaschen
+8  A: 

Another way to do it is with string.translate() and string.maketrans()

from string import maketrans
bitString = "10101010100011010"
flippedString = bitString.translate(maketrans("10","01"))
birryree
You might want to link to documentation slightly more recent than Python 2.3 - perhaps http://docs.python.org/library/string.html#string.translate
Amber
And http://docs.python.org/library/string.html#string.maketrans
Jon-Eric
Didn't even notice I was linking to such old documentation, thanks.
birryree
To be perfectly correct, you're (correctly) using this *method*: http://docs.python.org/library/stdtypes.html#str.translate not the deprecated string *function* Amber linked to.
Jon-Eric
@Jon-Eric - quite correct.
Amber
A: 

Using a dictionary should be very straightforward.

>>> flip={"1":"0","0":"1"}
>>> s="100011"
>>> import sys
>>> for i in s:
...   sys.stdout.write(flip[i])
...
011100
ghostdog74