Python - 在字符串中翻转二进制1和0

时间:2010-10-13 03:04:41

标签: python

我正在尝试以字符串形式获取二进制数并翻转1和0,即将字符串中的所有1更改为0,将所有0更改为1。我是Python的新手,现在已经花了好几个小时试图解决它。

9 个答案:

答案 0 :(得分:27)

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

a for b in c模式是生成器表达式,它根据不同的系列生成一系列项目。在这种情况下,原始系列是字符(因为你可以在Python中迭代字符串,它为你提供构成该字符串的字符),而新系列是一组字符,其中0和1翻转。

'1' if x == '0' else '0'非常简单 - 它为我们提供10不是x中的任何一个。我们对原始字符集中的每个x执行此操作,然后join()将它们全部放在一起(在每个项目之间使用空字符串'',也就是没有),从而给出我们是一个最后一个字符串,它是原始的所有相反字符的组合。

答案 1 :(得分:12)

另一种方法是使用string.translate()string.maketrans()

from string import maketrans
bitString = "10101010100011010"
flippedString = bitString.translate(maketrans("10","01"))

答案 2 :(得分:4)

如果速度很重要:

你已经有了表示二进制字符串的十进制整数,然后位操作稍快一些。

bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]

如果只给你二进制字符串,那么使用@Amy给出的str.replace方法:

s.replace('1', '2').replace('0', '1').replace('2', '0')

我测试了这里提出的各种方法,以及位操作方法this gist

测试结果

i = 129831201;
s = '111101111010001000100100001';

给定十进制int的位操作:

bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]

1000000 loops, best of 3: 0.647 usec per loop

给出二进制字符串的位操作:

bin((int(s, 2) ^ (2**(len(s)+1) - 1)))[3:]

1000000 loops, best of 3: 0.922 usec per loop

顺序str.replace

s.replace('1', '2').replace('0', '1').replace('2', '0')

1000000 loops, best of 3: 0.619 usec per loop

<强> str.maketrans

s.translate(str.maketrans('10', '01'))

1000000 loops, best of 3: 1.16 usec per loop
带有字典映射的

''.join

flip = {'1':'0', '0':'1'}; ''.join(flip[b] for b in s)

100000 loops, best of 3: 2.78 usec per loop
带有条件的

''.join

''.join('1' if b == '0' else '0' for b in s)

100000 loops, best of 3: 2.82 usec per loop

答案 3 :(得分:2)

Amber的回答虽然优越,但可能并不是最明确的,所以这是一个超级基本的迭代例子:

b_string = "1100101"
ib_string = ""

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

print ib_string

这可以用更好的方式完成......替换,理解,但这只是一个例子。

一旦你理解了这个问题的基础,我就会从这个问题的其他答案中学习。这种方法既缓慢又痛苦。对于最佳效果,正如 Muhammad Alkarouri 指出的那样,string.translate / maketrans组合是可行的方法。紧随其后的是理解力。我的代码是最慢的。

答案 4 :(得分:2)

使用字典应该非常简单。

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

答案 5 :(得分:1)

您已经标明了答案,但我还没有看到我更喜欢的方法。我在这里假设你有一个已知长度的二进制数 - 我给出的例子中有8位。

如果您可以将号码作为号码开头,则可以执行以下操作:

myNumber = 0b10010011
myNumberInverted = myNumber ^ 0b11111111

^运算符执行按位异或。

如果你真的必须以字符串开头,你可以先转换为整数,然后再执行此操作。

myString = '10010011'
myNumber = int(myString, 2)
myNumberInverted = myNumber ^ 0b11111111

答案 6 :(得分:0)

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

将所有的1替换为2,然后用1代替0,最后用0代替2。

"10011".replace("1", "2").replace("0", "1").replace("2", "0")

答案 7 :(得分:0)

沿着Amber的路线,但使用ASCII算法(没有特别的原因)。这显然不适用于生产代码。

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

48和49分别是'0'和'1'的ASCII(和Unicode)值。 ord为您提供了字符的数值,而chr却反过来。

答案 8 :(得分:0)

自回答此问题以来,有些事情已经改变。希望我的更新对某人有用。

对我而言,翻译方法是最快的。完整的测试代码如下。

谢谢那些以前为我做过贡献的人。

# System & Software
# core i7 4790k @ ~ 4.6 GHz   32 GB RAM   Samsung Evo NVME
# Visual Studio 2019 16.3.6

# I do not understand Will's bit manipulation code
# worst times shown in comments
# ordered by speed on my system

import timeit # required to use timeit
import string # Required to call maketrans function.

# https://www.afternerd.com/blog/timeit-multiple-lines/
# if you are trying to time slightly longer pieces of code than a single line
# timeit wants a string


# the syntax  b_string.translate(maketrans("10", "01"))
# presented by Muhammad Alkarouri does not appear to be valid anymore
# i suspect this is due to changes within python versions
a1_bit_flip = """\
a1 = 0b1101010001101111 # accepts the binary input but will store it as an int
a1_bin = bin(a1)[2:]
# creates a string of the binary form of the integer minus the first 2 characters
flip_bin_a1 = a1_bin.translate(str.maketrans("10","01"))"""

trans_time = timeit.timeit(a1_bit_flip, number=100000) # time 100k iterations
print('translate time')
print(trans_time / 100000)
# determine average time of a single iteration ~ 0.6282 us
print('\n')



a2_bit_flip = """\
a2 = 0b1101010001101111
a2_bin = bin(a2)[2:]
a2_bin.replace('1', '2').replace('0', '1').replace('2', '0')"""

replace_time = timeit.timeit(a2_bit_flip, number=100000) # time 100k iterations
print('replace time')
print(replace_time / 100000)
# determine average time of a single iteration ~ 0.7557 us
print('\n')



a3_bit_flip = """\
a3 = 0b1101010001101111
a3_bin = bin(a3)[2:]
bin((int(a3_bin, 2) ^ (2**(len(a3_bin)+1) - 1)))[3:]"""
# I do not understand this line (Will)

bin_bit_time = timeit.timeit(a3_bit_flip, number=100000)
# time 100k iterations
print('bin_bit time')
print(bin_bit_time / 100000)
# determine average time of a single iteration ~ 1.14 us
print('\n')



a4_bit_flip = """\
a4 = 0b1101010001101111
a4_bin = bin(a4)[2:]
bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]"""
# I do not understand this line (Will)

int_bit_time = timeit.timeit(a3_bit_flip, number=100000) # time 100k iterations
print('int_bit time')
print(int_bit_time / 100000)
# determine average time of a single iteration ~ 1.14 us
print('\n')



join_bit_flip = """\
a0 = 0b1101010001101111 # accepts the binary input but will store it as an int
a0_bin = bin(a0)[2:]
# creates a string of the binary form of the integer minus the first 2 characters
flip_a0 = "".join('1' if x == '0' else '0' for x in a0_bin)""" # (Amber)

join_time = timeit.timeit(join_bit_flip, number=100000) # time 100k iterations
print('join time')
print(join_time / 100000)
# determine average time of a single iteration ~ 14.511 us
print('\n')