How to replace multiple substrings at the same time [duplicate] - python

This question already has answers here:
How to replace multiple substrings of a string?
(28 answers)
Closed 7 months ago.
I have a string like
a = "X1+X2*X3*X1"
b = {"X1":"XX0","X2":"XX1","X0":"XX2"}
I want to replace the substring 'X1,X2,X3' using dict b.
However, when I replace using the below code,
for x in b:
a = a.replace(x,b[x])
print(a)
'XXX2+XX1*X3'
Expected result is XX0 + XX1*X3*XX0
I know it is because the substring is replaced in a loop, but I don't know how to solve it.

You can create a pattern with '|' then search in dictionary transform like below.
Try this:
import re
a = "X1+X2*X3*X1"
b = {"X1":"XX0","X2":"XX1","X0":"XX2"}
pattern = re.compile("|".join(b.keys()))
out = pattern.sub(lambda x: b[re.escape(x.group(0))], a)
Output:
>>> out
'XX0+XX1*X3*XX0'

You can use the repl parameter of re.sub:
import re
re.sub('X\d', lambda x: b.get(x.group(), x.group()), a)
output:
'XX0+XX1*X3*XX0'

The reason for this is beacuse you are replacing the same string multiple times, so behind the scenes (or between the iterations) there are a few more switches in the middle that you probably don't see (unless debugging this code).
Please note that dictionary keys are not ordered, so you cannot assume what's replaced when.
I suggest you use template
Edit: newer versions of python do preserve insertion order - Are dictionaries ordered in Python 3.6+?

With just built-in functions. The given b dictionary contains cycles between keys and values, so used the f-string notation to perform the substitutions. To escape the {} one should double them {{}}, used for repeated substitution. The enumerate is needed to get unique keys in the new dictionary, so no more cycles.
a = "X1+X2*X3*X1"
b = {"X1":"XX0","X2":"XX1","X0":"XX2"}
new_dict = {}
for i, k in enumerate(b):
sub_format = f'{k}' + f'{i}'
new_dict[sub_format] = b[k]
a = a.replace(k, f'{{{sub_format}}}')
print(a.format(**new_dict))
Output
XX0+XX1*X3*XX0

Related

How to replace variable with actual value inside the double quotes in Python?

I have one variable val = "O'brien" and I want to create a following string using this variable. -->
s1 = "{\"id1\":\"O'brien\"}"
I tried with this:
s1 = "{\"id1\":\"'{}'.format(x)\"}"
However, It's giving me literal values as
'{"id1":"\'{}\'.format(x)"}'
What I want instead is
s1 = "{\"id1\":\"O'brien\"}"
So that, I can make it dictionary using
json.loads(s1)
Which will give me this output:
{'id1': "O'brien"}.
I tried with many ways but couldn't get it, please suggest some good ways
There are multiple ways you can format your string, but this is how I would do it using an f string;
val = "O'brien"
s1 = f"{{\"id1\":\"{val}\"}}"
s1 is then equal to
{"id1":"O'Brien"}
If you want to use .format(x) it needs to be outside the outermost quote and you need to escape the outermost curly brackets
s1 = "{{\"id1\":\"{}\"}}".format(val)

Program to create a string from two given strings by concatenating the characters that are not contained by both strings

Write a Python program to create a string from two given strings by concatenating the characters that are not contained by both strings. The characters from the 1st string should appear before the characters from the 2nd string. Return the resulting string.
Sample input: ‘0abcxyz’, ‘abcxyz1’
Expected Output: ‘01’
I have already got the results but would like to learn if there is a better way to achieve the same results.'''
var14_1, var14_2 = '0abcxyz', 'abcxyz1'
def concat(var14_1,var14_2):
res = []
[res.append(s) for s in var14_1 if s not in var14_2]
[res.append(s) for s in var14_2 if s not in var14_1]
print(''.join(res))
concat(var14_1,var14_2)
The above code is returning the results as 01 which is as
expected. However I would like to know if there is any other way
to arrive at this solution without having to use "for loop"
twice. Your feedback will immensely help in improving my python skills. Thanks in advance!
It would be nicer to not use list comprehensions only to run many times res.append()
var14_1, var14_2 = '0abcxyz', 'abcxyz1'
r1 = [s for s in var14_1 if s not in var14_2]
r2 = [s for s in var14_2 if s not in var14_1]
res = r1 + r2
print(''.join(res))
To use one for loop you could convert strings to sets and get common chars
common = set('0abcxyz') & set('abcxyz1')
and then you can use one for with concatenated strings var14_1 + var14_2
common = set('0abcxyz') & set('abcxyz1')
res = [s for s in var14_1 + var14_2 if s not in common]
print(''.join(res))
Try this.
#furas pointed out you don't need list() while using set, so updated for that.
var14_1, var14_2 = '0abcxyz', 'abcxyz1'
def concat(first, second):
return ''.join(set(first).symmetric_difference(set(second)))
print(concat(var14_1, var14_2))
taking a set of an object creates an unordered collection of unique elements.
set()
has a function called symmetric_difference() which allows you to find the symmetric difference between two sets.

Which way is the best way to get a part of string in python? [duplicate]

This question already has answers here:
How to extract numbers from a string in Python?
(19 answers)
Closed 4 years ago.
I've learned python for a few months and I have a question.
Example I have a string s='string_123', I need to get "123" from s.
As I know, python provided some ways:
This question look likely with: Python: Extract numbers from a string
But, it mostly compare split() with regex. I need to know for detail of each way.
s.split("_")[-1]
s.partition("_")[2]
s[7:]
So which way is the best above? Or do we have any way else better than all?
The difference between split and partition is that partition will only split on the first occurrence of the given separator and returns that separator itself as well.
split will return an array of strings, separating the string based on the locations of the given separator and not including the separator in the array.
Take the string "a+b+c+d".
"a+b+c+d".split("+") # (= ["a", "b", "c", "d"])
"a+b+c+d".partition("+") # (= ("a", "+", "b+c+d"))
You can only use the s[7:] when you know that the underscore is exactly at position 6. This will also return everything after the underscore, so let's say we want to split the previous string based on the "+" sign, knowing that the plus is on position 1, we'll use the array notation:
"a+b+c+d"[2:] # (= "b+c+d")
You can combine that with find:
i = "a+b+c+d".find("+")
"a+b+c+d"[i+1:] # ( = "b+c+d")
You could also do:
>>> import re
>>> re.findall(r'\d+', s)[0]
'123'
This uses regular expression to identify the digits in your string, and split them into a list. [0] selects the first instance of digits that appear in the string.
From any aspect, you need to tell it is the best like how fast, memory used, complexity. So, it depends on your needs.
For example, the simplest way is to use:
s='string_123'
end = None
print(s[7:end])
If you don't know where is the _ use this
s='string_123'
index=0
for i in s:
index=index+1
if i=='_':
break;
end = None
print(s[index:end])
For split the string
print(s.split('_'))
code here:https://repl.it/repls/LoneJuicyThings?folderId=

Python > passing variables of a string into a method

I'm looking to replace a list of characters (including escaped characters) with another.
for example:
l=['\n','<br>','while:','<while>','for:','<for>']
s='line1\nline2'
s.replace(l[0],[l[1])
but passing the list indices through the method produces no effect.
I've also tried using
s=l[1].join(s.split(l[0]))
How can I replace a list of characters with another without expressing the pairs each time in the function?
As I said in the comments, the problem with your code is that you assumed that the replace works in-place. It does not, you have to assign the value it returns to the variable.
But, there is a better way of doing it that involves dictionaries. Take a look:
d = {'\n': '<br>', 'while:': '<while>', 'for:': '<for>'}
s = 'line1\nline2\nwhile: nothing and for: something\n\nnothing special'
for k, v in d.items():
s = s.replace(k, v)
print(s) # line1<br>line2<br><while> nothing and <for> something<br><br>nothing special
The advantage of using dictionaries in this case is that you make it very straightforward what you want to replace and what with. Playing with the indexes is not something you want to do if you can avoid it.
Finally, if you are wondering how to convert your list to a dict you can use the following:
d = {k: v for k, v in zip(l[::2], l[1::2])}
which does not break even if your list has an odd number of elements.
l=['\n','<br>','while:','<while>','for:','<for>']
s='line1\nline2'
for i in range(0, len(l), 2):
s = s.replace(l[i], l[i+1])
You simply have to iterate over the list containing your desired pairs, stepping over 2 values each time. And then assign the result of the replacement to the variable itself (replace doesn't do inline replacement because strings are inmutable in Python)

Breaking 1 String into 2 Strings based on special characters using python

I am working with python and I am new to it. I am looking for a way to take a string and split it into two smaller strings. An example of the string is below
wholeString = '102..109'
And what I am trying to get is:
a = '102'
b = '109'
The information will always be separated by two periods like shown above, but the number of characters before and after can range anywhere from 1 - 10 characters in length. I am writing a loop that counts characters before and after the periods and then makes a slice based on those counts, but I was wondering if there was a more elegant way that someone knew about.
Thanks!
Try this:
a, b = wholeString.split('..')
It'll put each value into the corresponding variables.
Look at the string.split method.
split_up = [s.strip() for s in wholeString.split("..")]
This code will also strip off leading and trailing whitespace so you are just left with the values you are looking for. split_up will be a list of these values.

Categories

Resources