Python - 翻转字符串中的二进制 1 和 0
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3920494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python - Flipping Binary 1's and 0's in a String
提问by Just a Student
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 racking my brain for several hours now trying to figure it out.
我试图取字符串形式的二进制数并翻转 1 和 0,即将字符串中的所有 1 更改为 0,并将所有 0 更改为 1。我是 Python 的新手,现在已经绞尽脑汁想弄明白几个小时了。
采纳答案by Xorlev
Amber's answer, while superior, possibly isn't the most clear, so here's a super basic iterative example:
Amber 的回答虽然优秀,但可能不是最清楚的,所以这是一个超级基本的迭代示例:
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 betterways...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 bestperformance, as Muhammad Alkarouripointed out, the string.translate/maketranscombo is the way to go. Right behind it is the comprehension. My code is the slowest by a significant margin.
一旦你理解了这个问题的基础,我就会从这个问题的其他答案中学习。这种方法缓慢而痛苦。为了获得最佳性能,正如穆罕默德·阿尔卡鲁里( Muhammad Alkarouri)指出的那样,string.translate/maketrans组合是要走的路。紧随其后的是领悟。我的代码是最慢的。
回答by Amber
>>> ''.join('1' if x == '0' else '0' for x in '1000110')
'0111001'
The a for b in cpattern 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.
该a for b in c模式是一个生成器表达式,它根据不同的系列生成一系列项目。在这种情况下,原始系列是字符(因为您可以在 Python 中迭代字符串,从而为您提供组成该字符串的字符),而新系列是一组翻转了 0 和 1 的字符。
'1' if x == '0' else '0'is pretty straightforward - it gives us whichever of 1or 0isn't x. We do this for each such xin 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.
'1' if x == '0' else '0'是非常简单-它给我们取的1或0不是x。我们x对原始字符集中的每个这样的字符执行此操作,然后将join()它们全部放在一起(''在每个项目之间使用一个空字符串,也就是什么都没有),从而给我们一个最终字符串,它是与原始字符相反的所有字符,结合。
回答by Amy
http://docs.python.org/library/string.html#string.replace
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.
将所有的 1 替换为 2,然后将 0 替换为 1,最后将 2 替换为 0。
"10011".replace("1", "2").replace("0", "1").replace("2", "0")
回答by Matthew Flaschen
Along the lines of Amber, but using ASCII arithmetic (for no particular reason). This obviously isn't meant for production code.
沿着 Amber 的路线,但使用 ASCII 算术(没有特别的原因)。这显然不适用于生产代码。
''.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. ordgives you the numeric value for a character, while chrdoes the reverse.
回答by wkl
Another way to do it is with string.translate()and string.maketrans()
另一种方法是使用string.translate()和string.maketrans()
from string import maketrans
bitString = "10101010100011010"
flippedString = bitString.translate(maketrans("10","01"))
回答by ghostdog74
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
回答by Will
If speed is important:
如果速度很重要:
And you already have the decimal integer representing the binary string, then bit manipulation is slightly faster.
并且您已经有了表示二进制字符串的十进制整数,那么位操作会稍微快一些。
bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]
If you are only given the binary string, then use the str.replacemethod given by @Amy:
如果你只得到二进制字符串,那么使用str.replace@Amy 给出的方法:
s.replace('1', '2').replace('0', '1').replace('2', '0')
I tested the various methods proposed here, and the bit manipulation method, with this gist:
我使用以下要点测试了此处提出的各种方法和位操作方法:
Test Results
检测结果
i = 129831201;
s = '111101111010001000100100001';
Bit manipulation given decimal int:
位操作给定十进制int:
bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]
1000000 loops, best of 3: 0.647 usec per loop
Bit manipulation given binary string:
给定二进制字符串的位操作:
bin((int(s, 2) ^ (2**(len(s)+1) - 1)))[3:]
1000000 loops, best of 3: 0.922 usec per loop
Sequential str.replace:
顺序str.replace:
s.replace('1', '2').replace('0', '1').replace('2', '0')
1000000 loops, best of 3: 0.619 usec per loop
str.maketrans:
str.maketrans:
s.translate(str.maketrans('10', '01'))
1000000 loops, best of 3: 1.16 usec per loop
''.joinwith dictionary mapping:
''.join使用字典映射:
flip = {'1':'0', '0':'1'}; ''.join(flip[b] for b in s)
100000 loops, best of 3: 2.78 usec per loop
''.joinwith conditional:
''.join有条件的:
''.join('1' if b == '0' else '0' for b in s)
100000 loops, best of 3: 2.82 usec per loop
回答by Ian
You've already marked an answer to this, but I haven't seen the method that I would prefer. I'm assuming here that you have a binary number of known length - 8 bits in the examples I am giving.
您已经为此标记了一个答案,但我还没有看到我更喜欢的方法。我在这里假设您有一个已知长度的二进制数 - 在我给出的示例中为 8 位。
If you can start with the number as just a number, you can do the following:
如果您可以将数字作为数字开头,则可以执行以下操作:
myNumber = 0b10010011
myNumberInverted = myNumber ^ 0b11111111
The ^operator performs a bitwise XOR.
该^运算符执行按位异或。
If you really do have to start with a string, you can convert to an integer first and then perform this operation.
如果确实必须以字符串开头,则可以先转换为整数,然后再执行此操作。
myString = '10010011'
myNumber = int(myString, 2)
myNumberInverted = myNumber ^ 0b11111111
回答by John Lutz
Some things have changed since this question was answered. Hopefully my update proves useful to someone.
自从回答这个问题以来,有些事情发生了变化。希望我的更新对某人有用。
The translate method is the fastest for me. Full test code follows.
翻译方法对我来说是最快的。完整的测试代码如下。
Thank you to those who contributed previously to allow me to test this.
感谢之前做出贡献的人,让我测试这个。
# 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')

