我正在尝试以字符串形式获取二进制数并翻转1和0,即将字符串中的所有1更改为0,将所有0更改为1。我是Python的新手,现在已经花了好几个小时试图解决它。
答案 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'
非常简单 - 它为我们提供1
或0
不是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)
答案 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')