kcrisman
kcrisman

Reputation: 4402

Permuting characters in a string

Warning: this question is not what you think!


Suppose I have a string like this (Python):

'[[1, 2], [2, 3], [0, 3]]'

Now suppose further that I have the permutation of the characters 0, 1, 2, 3 which swaps 0 and 1, as well as (separately) 2 and 3. Then I would wish to obtain

'[[0, 3], [3, 2], [1, 2]]'

from this. As another example, suppose I want to use the more complicated permutation where 1 goes to 2, 2 goes to 3, and 3 goes to 1? Then I would desire the output

 '[[2, 3], [3, 1], [0, 1]]'

Question: Given a permutation (encoded however one likes) of characters/integers 0 to n-1 and a string containing (some of) them, I would like a function which takes such a string and gives the appropriate resulting string where these characters/integers have been permuted - and nothing else.

I have been having a lot of difficult seeing whether there is some obvious use of re or even just indexing that will help me, because usually these replacements are sequential, which would obviously be bad in this case. Any help will be much appreciated, even if it makes me look dumb.

(If someone has an idea for the original list [[1, 2], [2, 3], [0, 3]], that is fine too, but that is a list of lists and presumably more annoying than a string, and the string would suffice for my purposes.)

Upvotes: 0

Views: 176

Answers (5)

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

Here's a simple solution using a regular expression with callback:

import re

s = '[[1, 2], [2, 3], [0, 3]]'

map = [3, 2, 1, 0]

print(re.sub('\d+',                                 # substitute all numbers
             lambda m : str(map[int(m.group(0))]),  # ... with the mapping
             s                                      # ... for string s
            )
)

# output: [[2, 1], [1, 0], [3, 0]]

Upvotes: 2

Ajax1234
Ajax1234

Reputation: 71451

You can build a mapping of your desired transformations:

import ast
d = ast.literal_eval('[[1, 2], [2, 3], [0, 3]]')
m = {1: 2, 2: 3, 3: 1}
new_d = [[m.get(i) if i in m else 
        (lambda x:i if not x else x[0])([a for a, b in m.items() if b == i]) for i in b] for b in d]

Output:

[[2, 3], [3, 1], [0, 1]]

For the first desired swap:

m = {0:1, 2:3}
d = ast.literal_eval('[[1, 2], [2, 3], [0, 3]]')
new_d = [[m.get(i) if i in m else 
    (lambda x:i if not x else x[0])([a for a, b in m.items() if b == i]) for i in b] for b in d]

Output:

[[0, 3], [3, 2], [1, 2]]

Upvotes: 1

bipll
bipll

Reputation: 11940

permutation = {'0':'1', '1':'0', '2':'3', '3':'2'}
s = '[[1, 2], [2, 3], [0, 3]]'
rv = ''

for c in s:
   rv += permutation.get(c, c)

print(rv)

?

Upvotes: 1

Sebastien D
Sebastien D

Reputation: 4482

This is absolutely inelegant regarding the quality of this forum I confess but here is my suggestion just to help:

string = '[[1, 2], [2, 3], [0, 3]]'
numbers = dict(zero = 0, one = 1, two = 2, three=3, four = 4, five = 5, six=6, seven=7, height=8, nine = 9)
string = string.replace('0', 'one').replace('1', 'zero').replace('2','three').replace('3', 'two')

for x in numbers.keys():
    string = string.replace(x, str(numbers[x]))

[[0, 3], [3, 2], [1, 2]]

Upvotes: 0

spinkus
spinkus

Reputation: 8550

Well I think in general you'll need to use a working memory copy of the resultant to avoid the sequential issue you mention. Also converting to some structured data format like an array to work in makes things much easier (you don't say so but your target string is clearly a stringified array so I'm taking that for granted). Here is one idea using eval and numpy:

import numpy as np

s =  '[[2, 3], [3, 1], [0, 1]]'
a = np.array(eval(s))
print('before\n', a)
mymap = [1,2,3,0]
a = np.array([mymap[i] for i in a.flatten()]).reshape(a.shape)
print('after\n', a)

Gives:

before
 [[2 3]
 [3 1]
 [0 1]]
after
 [[3 0]
 [0 2]
 [1 2]]

Upvotes: 1

Related Questions