Given a list :
q = ['"hello','it's','me']
I want to remove "'s" and the '"' at the beginning of hello to obtain:
q = ['hello','it','me']
I wrote:
for i in ['"s','"']:
q = [w.replace(i,'') for w in q]
This results in q=['"hello",'it','me']. The code does not seem to work for the quotation marks.
(I cannot comment because I don't have enought points so please excuse me for posting as an answer).
First your initial list q is not valid, the 'it's element will throw invalid syntax.
The easiest will be to sanitize your list elements before they're pushed, is this possible for you? For example, in the case of double quotes use
element = '"hello'
element.replace('"', '')
In the case of the single quote and the s:
element = "it's"
single_index = element.find("'")
new_element = element[0:single_index]
I hope this helps
Related
Task
Write a program that will decode the secret message by reversing text
between square brackets. The message may contain nested brackets (that
is, brackets within brackets, such as One[owT[Three[ruoF]]]). In
this case, innermost brackets take precedence, similar to parentheses
in mathematical expressions, e.g. you could decode the aforementioned
example like this:
One[owT[Three[ruoF]]]
One[owT[ThreeFour]]
One[owTruoFeerhT]
OneThreeFourTwo
In order to make your own task slightly easier and less tricky, you
have already replaced all whitespaces in the original text with
underscores (“_”) while copying it from the paper version.
Input description
The first and only line of the standard input
consists of a non-empty string of up to 2 · 106 characters which may
be letters, digits, basic punctuation (“,.?!’-;:”), underscores (“_”)
and square brackets (“[]”). You can safely assume that all square
brackets are paired correctly, i.e. every opening bracket has exactly
one closing bracket matching it and vice versa.
Output description
The standard output should contain one line – the
decoded secret message without any square brackets.
Example
For sample input:
A[W_[y,[]]oh]o[dlr][!]
the correct output is:
Ahoy,_World!
Explanation
This example contains empty brackets. Of course, an empty string, when
reversed, remains empty, so we can simply ignore them. Then, as
previously, we can decode this example in stages, first reversing the
innermost brackets to obtain A[W_,yoh]o[dlr][!]. Afterwards, there
are no longer any nested brackets, so the remainder of the task is
trivial.
Below is my program that doesn't quite work
word = input("print something: ")
word_reverse = word[::-1]
while("[" in word and "]" in word):
open_brackets_index = word.index("[")
close_brackets_index = word_reverse.index("]")*(-1)-1
# print(word)
# print(open_brackets_index)
# print(close_brackets_index)
reverse_word_into_quotes = word[open_brackets_index+1:close_brackets_index:][::-1]
word = word[:close_brackets_index]
word = word[:open_brackets_index]
word = word+reverse_word_into_quotes
word = word.replace("[","]").replace("]","[")
print(word)
print(word)
Unfortunately my code only works with one pair of parentheses and I don't know how to fix it.
Thank you in advance for your help
Assuming the re module can be used, this code does the job:
import re
text = 'A[W_[y,[]]oh]o[dlr][!]'
# This scary regular expresion does all the work:
# It says find a sequence that starts with [ and ends with ] and
# contains anything BUT [ and ]
pattern = re.compile('\[([^\[\]]*)\]')
while True:
m = re.search(pattern, text)
if m:
# Here a single pattern like [String], if any, is replaced with gnirtS
text = re.sub(pattern, m[1][::-1], text, count=1)
else:
break
print(text)
Which prints this line:
Ahoy,_World!
I realize the my previous answer has been accepted but, for completeness, I'm submitting a second solution that does NOT use the re module:
text = 'A[W_[y,[]]oh]o[dlr][!]'
def find_pattern(text):
# Find [...] and return the locations of [ (start) ] (end)
# and the in-between str (content)
content = ''
for i,c in enumerate(text):
if c == '[':
content = ''
start = i
elif c == ']':
end = i
return start, end, content
else:
content += c
return None, None, None
while True:
start, end, content = find_pattern(text)
if start is None:
break
# Replace the content between [] with its reverse
text = "".join((text[:start], content[::-1], text[end+1:]))
print(text)
Have a scenario where I wanted to split a string partially and pick up the 1st portion of the string.
Say String could be like aloha_maui_d0_b0 or new_york_d9_b10. Note: After d its numerical and it could be any size.
I wanted to partially strip any string before _d* i.e. wanted only _d0_b0 or _d9_b10.
Tried below code, but obviously it removes the split term as well.
print(("aloha_maui_d0_b0").split("_d"))
#Output is : ['aloha_maui', '0_b0']
#But Wanted : _d0_b0
Is there any other way to get the partial portion? Do I need to try out in regexp?
How about just
stArr = "aloha_maui_d0_b0".split("_d")
st2 = '_d' + stArr[1]
This should do the trick if the string always has a '_d' in it
You can use index() to split in 2 parts:
s = 'aloha_maui_d0_b0'
idx = s.index('_d')
l = [s[:idx], s[idx:]]
# l = ['aloha_maui', '_d0_b0']
Edit: You can also use this if you have multiple _d in your string:
s = 'aloha_maui_d0_b0_d1_b1_d2_b2'
idxs = [n for n in range(len(s)) if n == 0 or s.find('_d', n) == n]
parts = [s[i:j] for i,j in zip(idxs, idxs[1:]+[None])]
# parts = ['aloha_maui', '_d0_b0', '_d1_b1', '_d2_b2']
I have two suggestions.
partition()
Use the method partition() to get a tuple containing the delimiter as one of the elements and use the + operator to get the String you want:
teste1 = 'aloha_maui_d0_b0'
partitiontest = teste1.partition('_d')
print(partitiontest)
print(partitiontest[1] + partitiontest[2])
Output:
('aloha_maui', '_d', '0_b0')
_d0_b0
The partition() methods returns a tuple with the first element being what is before the delimiter, the second being the delimiter itself and the third being what is after the delimiter.
The method does that to the first case of the delimiter it finds on the String, so you can't use it to split in more than 3 without extra work on the code. For that my second suggestion would be better.
replace()
Use the method replace() to insert an extra character (or characters) right before your delimiter (_d) and use these as the delimiter on the split() method.
teste2 = 'new_york_d9_b10'
replacetest = teste2.replace('_d', '|_d')
print(replacetest)
splitlist = replacetest.split('|')
print(splitlist)
Output:
new_york|_d9_b10
['new_york', '_d9_b10']
Since it replaces all cases of _d on the String for |_d there is no problem on using it to split in more than 2.
Problem?
A situation to which you may need to be careful would be for unwanted splits because of _d being present in more places than anticipated.
Following the apparent logic of your examples with city names and numericals, you might have something like this:
teste3 = 'rio_de_janeiro_d3_b32'
replacetest = teste3.replace('_d', '|_d')
print(replacetest)
splitlist = replacetest.split('|')
print(splitlist)
Output:
rio|_de_janeiro|_d3_b32
['rio', '_de_janeiro', '_d3_b32']
Assuming you always have the numerical on the end of the String and _d won't happen inside the numerical, rpartition() could be a solution:
rpartitiontest = teste3.rpartition('_d')
print(rpartitiontest)
print(rpartitiontest[1] + rpartitiontest[2])
Output:
('rio_de_janeiro', '_d', '3_b32')
_d3_b32
Since rpartition() starts the search on the String's end and only takes the first match to separate the terms into a tuple, you won't have to worry about the first term (city's name?) causing unexpected splits.
Use regex's split and keep delimiters capability:
import re
patre = re.compile(r"(_d\d)")
#👆 👆
#note the surrounding parenthesises - they're what drives "keep"
for line in """aloha_maui_d0_b0 new_york_d9_b10""".split():
parts = patre.split(line)
print("\n", line)
print(parts)
p1, p2 = parts[0], "".join(parts[1:])
print(p1, p2)
output:
aloha_maui_d0_b0
['aloha_maui', '_d0', '_b0']
aloha_maui _d0_b0
new_york_d9_b10
['new_york', '_d9', '_b10']
new_york _d9_b10
credit due: https://stackoverflow.com/a/15668433
I have looked over similar questions, but I still have trouble figuring this one out.
I have two Lists of strings, one of which consists of characters like 'abcdefg' and another one consisting of strings which consist of white spaces and a special character. The special character indicates where I should remove characters from my 'abcdefg' string. The special character's position in the list would be the same position I would need to remove a character from the first list. I also need to remove the adjacent characters.
EDIT: I want to remove a character (and the adjacent characters) at the same position the '*' char is located in airstrikes, but in reinforces. Does this make sense?
reinforces = ["abcdefg", "hijklmn"]
airstrikes = [" * "]
battlefield = reinforces[0]
bomb_range = []
count = 0
if range(len(airstrikes)) != 0:
for airstrike in airstrikes:
for char in airstrike:
print(count)
count = count + 1
if (char == '*'):
bomb_range.append(count-1)
bomb_range.append(count)
bomb_range.append(count+1)
break
#Trying to hardcode it initially just to get it to work. Some kind of looping is needed though.
battlefield = battlefield[:bomb_range[0]] + battlefield[bomb_range[1]:]
battlefield = battlefield[:bomb_range[1]] + battlefield[bomb_range[2]:]
#battlefield = battlefield[:bomb_range[2]] + battlefield[bomb_range[3]:] #Will not work of course. But how could I achieve what I want?
I am sorry about the nested loops. If it hurts looking at it, feel free to bash and correct me. I am sorry if I missed any answers on this forum which could have helped me find a solution. Know that I did try to find one.
Use index to find where to strike, then remove the character the usual way:
>>> reinforce = "abcdefg"
>>> airstrike = " * "
>>> strike_at = airstrike.index('*')
>>> reinforce[:strike_at]+reinforce[strike_at+1:]
'abcefg'
of course, you need to make sure strike_at+1 is a legal index (see try and except).
I am trying to get users who are mentioned in an article. That is, words starting with # symbol and then wrap < and > around them.
WHAT I TRIED:
def getUsers(content):
users = []
l = content.split(' ')
for user in l:
if user.startswith('#'):
users.append(user)
return users
old_string = "Getting and replacing mentions of users. #me #mentee #you #your #us #usa #wo #world #word #wonderland"
users = getUsers(old_string)
new_array = old_string.split(' ')
for mention in new_array:
for user in users:
if mention == user and len(mention) == len(user):
old_string = old_string.replace(mention, '<' + user + '>')
print old_string
print users
The code is behaving funny. It wraps words starting with the same alphabets and even truncate subsequent as shown in the print below:
RESULT:
Getting and replacing mentions of users. <#me> <#me>ntee <#you> <#you>r <#us> <#us>a <#wo> <#wo>rld <#wo>rd <#wo>nderland
['#me', '#mentee', '#you', '#your', '#us', '#usa', '#wo', '#world', '#word', '#wonderland']
EXPECTED RESULT:
Getting and replacing mentions of users. <#me> <#mentee> <#you> <#your> <#us> <#usa> <#wo> <#world> <#word> <#wonderland>
['#me', '#mentee', '#you', '#your', '#us', '#usa', '#wo', '#world', '#word', '#wonderland']
Process finished with exit code 0
Why is this happening and how can do this the right way?
Why this happens: When you split the string, you put a lot of checks in to make sure you are looking at the right user e.g. you have #me and #mentee - so for user me, it will match the first, and not the second.
However, when you do replace, you are doing replace on the whole string - so when you say to replace e.g. #me with <#me>, it doesn't know anything about your careful split - it's just going to look for #me in the string and replace it. So #mentee ALSO contains #me, and will get replaced.
Two (well, three) choices: One is to add the spaced around it, to gate it (like #parchment wrote).
Second is to use your split: Instead of replacing the original string, replace the local piece. The simplest way to do this is with enumerate:
new_array = old_string.split(' ')
for index, mention in enumerate(new_array):
for user in users:
if mention == user and len(mention) == len(user):
#We won't replace this in old_string, we'll replace the current entry
#old_string = old_string.replace(a, '<' + user + '>')
new_array[index] = '<%s>'%user
new_string = ' '.join(new_array)
Third way... this is a bit more complex, but what you really want is for any instance of '#anything' to be replaced with <#anything> (perhaps with whitespace?). You can do this in one shot with re.sub:
new_string = re.sub(r'(#\w+)', r'<\g<0>>', old_string)
My previous answer was based entirely on correcting the problems in your current code. But, there is a better way to do this, which is using regular expressions.
import re
oldstring = re.sub(r'(#\w+)\b', r'<\1>', oldstring)
For more information, see the documentation on the re module.
Because #me occurs first in your array, your code replaces the #me in #mentee.
Simplest way to fix that is to add a space after the username that you want to be replaced:
old_string = old_string.replace(a + ' ', '<' + user + '> ')
# I added space here ^ and here ^
A new problem occurs, though. The last word is not wrapped, because there's no space after it. A very simple way to fix it would be:
oldstring = oldstring + ' '
for mention in ... # Your loop
oldstring = oldstring[:-1]
This should work, as long as there isn't any punctuation (like commas) next to the usernames.
def wrapUsers(content):
L = content.split()
newL = []
for word in L:
if word.startswith('#'): word = '<'+word+'>'
newL.append(word)
return " ".join(newL)
Using Python v2, is there a way to ignore a value in a string if it is there?
For instance: I want someone to enter a value of $100.00, or they could enter a value of 100.00 without the leading $ symbol. What I want to do is ignore the '$' value if it is typed in.
Any push in the right direction would be appreciated.
Maybe
s = " $100.00 "
f = float(s.strip().lstrip("$"))
The .strip() strips whitespace from the beginning and the end of the string, and the .lstrip("$") strips a dollar sign from the beginning, if present.
If you only want to remove a '$' then s.replace('$', '') will do want you want.
If you want to replace more than one character then you need to chain replace calls together, which gets very ugly very quickly and in that case one of the other solutions is probably better.
Just filter out unwanted characters from the string. There are multiple ways of doing this, for clarity you could use:
def clean(s, wanted = "0123456789."):
"""Returns version of s without undesired characters in it."""
out = ""
for c in s:
if c in wanted:
out += c
return out
To avoid the dynamic string-building, which is costly, you can build a list and then turn the list into a string:
def clean2(s, wanted = "0123456789."):
outlist = [c for c in s if c in wanted]
return "".join(outlist)
You could simply use a regular expression to extract the number from the string.
Or your could be lazy if you just want to remove a leading $:
if s.startswith('$'):
s = s[1:]
If you want to remove multiple $ signs, replace if with while or use s = s.lstrip('$')
PS: You might want to remove trailing $ signs, too. rstrip() or endswith() and s[:-1] are your friends in this case.
Just lstrip $ from the string before you process it.
value = ...
value = value.lstrip( ' $' ) # Strip blank and $
a = "$100.00"
b = ''.join((c for c in a if c != "$"))
of course this is reasonable if you don't know the position of the character you want to remove