1

At the moment I'm doing it like this but the problem is I'm looping through thousands of such strings (which are all much longer than the example string given below) and current method takes a very long time to complete:

    example_string = '1001011101010010101010100100000001111011010101'
    reversed = ''
    for c in example_string:
        if c == '1':
            reversed += '0'
        elif c == '0':
            reversed += '1'
    print(reversed)

Mr Squidr
  • 143
  • 1
  • 8
  • You're also discarding everything that is neither one nor zero. Why would you pick such an inefficient way of storing binary numbers to begin with? Anyhow, the inefficient part is putting together a string from single characters. – Ulrich Eckhardt May 17 '20 at 14:58
  • 1
    Does this answer your question? [What is the most efficient string concatenation method in python?](https://stackoverflow.com/questions/1316887/what-is-the-most-efficient-string-concatenation-method-in-python) – Ulrich Eckhardt May 17 '20 at 14:58
  • 1
    You can use this single line statement: `"".join(['1' if chr == '0' else '0' for chr in example_string])` – Saurabh May 17 '20 at 15:11

4 Answers4

7
example_string.translate(str.maketrans("01","10"))
Martin Nečas
  • 593
  • 2
  • 9
  • This works and is the fastest solution so far for sure. It's about 4x faster than my previous solution. Unfortunately it's still quite slow and the amount of strings I have to process is quite large so it still takes about a minute (before it was 4min). Strings might be too slow for what I'm after. Will try to come up with some sort of boolean solution perhaps. – Mr Squidr May 17 '20 at 16:06
  • @MrSquidr I think you can do even faster using bit manipulation – Tom May 17 '20 at 16:30
  • Yeah I was thinking about it but when it starts with 0 it is cut not sure if you mind but here is example `bin((1 << len(example_string)) - 1 ^ int(example_string,2))[2:]` will update the answer and please let me know if it resolves it. – Martin Nečas May 17 '20 at 16:39
1

using strings to store binary numbers is not a very good option, but when using string it is better to use a list instead of a string to store the result of the reversing. every time you do reserved += '0' reserved is copied into memory, which takes a long time, but with lists it is not as slow. try this:

reversed = []
for c in example_string:
    if c == '1':
        reversed.append('0')
    elif c == '0':
        reversed.append('1')
print(''.join(reversed))
Gal
  • 504
  • 4
  • 11
1

If speed is really important

You can use bit manipulation:

example_string = '1001011101010010101010100100000001111011010101'
reverted = ''

i = int(example_string, 2)

reverted = bin((i ^ (2 ** (i.bit_length()+1) - 1)))[-len(example_string):]

print(reverted)


# reverted : 0110100010101101010101011011111110000100101010
Community
  • 1
  • 1
Tom
  • 677
  • 7
  • 21
  • Thanks, speed is really important. I like the logic in your solution but upon testing it it looks like it's slower than solution from Martin. Quite odd as it would logically seem that calculating solution mathematically would make it much faster. – Mr Squidr May 17 '20 at 16:39
  • @MrSquidr Thank for the feedback. Do you have a dataset example ? What is the average string lenght ? – Tom May 17 '20 at 16:41
  • Most of them are 10,240,000 characters long (so MSB is 2^(10,240,000-1)). I could give you few examples but they are to the eye just random 0/1. On average there is equal amount of 0's and 1's. – Mr Squidr May 17 '20 at 16:48
  • Thanks. Quite odd, on my side using bit manipulation is 3 time faster than using `translate` (on string of 10,240,000 characters). – Tom May 17 '20 at 17:05
1

Using bitwise operators:

s = '1001011101010010101010100100000001111011010101'

i = int(s,2)
i=((1<<i.bit_length())-1)^i
t=bin(i)[2:].zfill(len(s))
print(s)
print(t)

Output:

1001011101010010101010100100000001111011010101
0110100010101101010101011011111110000100101010

Explanation:

First I convert the string to an integer (s -> i).
Then I make a number that has the same length as i in binary but has all ones.
This is achieved by bitshifting 1 to the left n times where n is the length of the binary string, it's safer to use the .bit_length() method of the integer though. This bitshifted integer is still the power of two so we have to subtract 1 to get all ones. Then using the xor (exclusive or) operator the result will be the opposite of the input's. After this it's just changing back to binary string, removing the 0b part from the start and filling with zeroes to the left to match the length of the original string.

Gábor Fekete
  • 1,343
  • 8
  • 16