How do I replace a string at a index in python? [duplicate] - python

This question already has answers here:
Changing one character in a string
(15 answers)
Closed 1 year ago.
So I already know how to remove a index like this:
i = "hello!"
i= i[:0] + i[1:]
print(i)
'ello!'
But how do I replace it?
So maybe I wanted to now put a H where the old h was but if I do this:
i[0] ="H"
I get this error:
Traceback (most recent call last):
File "<pyshell#2>", line 1, in
i[0] ="H"
TypeError: 'str' object does not support item assignment
How do I fix this?

Strings are immutable in Python, so you can't assign like i[0] = 'H'. What you can do is convert the string to list, which is mutable, then you can assign new values at a certain index.
i = "hello!"
i_list = list(i)
i_list[0] = 'H'
i_new = ''.join(i_list)
print(i_new)
Hello!

Without creating a list you could also do:
i = "hello!"
i = "H" + i[1:]
More general:
def change_letter(string, letter, index): # note string is actually a bad name for a variable
return string[:index] + letter + string[index+1:]
s = "hello!"
s_new = change_letter(s, "H", 0)
print(s_new)
# should print "Hello!"
Also note there is a built in function .capitalize()

This is a duplicate of this post
As said there you have to make a list out of your string and change the char by selecting an item from that list and reassigning a new value and then in a loop rebuilding the string.
>>> s = list("Hello zorld")
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'z', 'o', 'r', 'l', 'd']
>>> s[6] = 'W'
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']
>>> "".join(s)
'Hello World'

i = "hello!"
print(i) ## will print hello!
i = "H" + i[1:]
print(i) ## will print Hello!

Related

Getting the index of the word 'print' in a multiline string

I am trying to find the index of all the word: 'print' in a multi line text. But there are some problems, those are:
The code returns the index same of word 'print' two time if there are two prints in a line.
It is not able to find the index of the second 'print' in the same line, but prints the index of the first 'print' two times.
My code is:
text = '''print is print as
it is the function an
print is print and not print
'''
text_list = []
for line in text.splitlines():
#'line' represents each line in the multiline string
text_list.append([])
for letter in line:
#Append the letter of each line in a list inside the the text_list
text_list[len(text_list)-1].append(letter)
for line in text_list:
for letter in line:
#check if the letter is after 'p' is 'r' and after that 'i' and then 'n' and at last 't'
if letter == "p":
num = 1
if text_list[text_list.index(line)][line.index(letter)+num] == 'r':
num += 1
if text_list[text_list.index(line)][line.index(letter)+num] == 'i':
num += 1
if text_list[text_list.index(line)][line.index(letter)+num] == 'n':
num += 1
if text_list[text_list.index(line)][line.index(letter)+num] == 't':
num += 1
print(f'index (start,end) = {text_list.index(line)}.{line.index(letter)}, {text_list.index(line)}.{line.index(letter)+num}')
when I run it prints:
index (start,end) = 0.0, 0.5 #returns the index of the first 'print' in first line
index (start,end) = 0.0, 0.5 #returns the index of the first 'print' in first line instead of the index of the second print
index (start,end) = 2.0, 2.5 #returns the index of the first 'print' in third line
index (start,end) = 2.0, 2.5 #returns the index of the first 'print' in third line instead of the index of the second print
index (start,end) = 2.0, 2.5 #returns the index of the first 'print' in third line instead of the index of the third print
you can see that in the result, the index are repeated. This is the text_list:
>>> text_list
[['p', 'r', 'i', 'n', 't', ' ', 'i', 's', ' ', 'p', 'r', 'i', 'n', 't', ' ', 'a', 's'],
['i', 't', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', ' ', 'a', 'n'],
['p', 'r', 'i', 'n', 't', ' ', 'i', 's', ' ', 'p', 'r', 'i', 'n', 't', ' ', 'a', 'n', 'd', ' ', 'n', 'o', 't', ' ', 'p', 'r', 'i', 'n', 't']]
>>>
each list inside the text_list is a line in the text. There are three lines, so there are three lists inside the text_list. How do I get the index of the second 'print' in the first line and the index of second and third 'print' in the third line? You can see that it returns only the index of first 'print' in the first and third line.
import re
text = '''print is print as
it is the function an
print is print and not print
'''
for line_number, line in enumerate(text.split('\n')):
occurrences = [m.start() for m in re.finditer('print', line)]
if occurrences:
for occurrence in occurrences:
print('Found `print` at character %d on line %d' % (occurrence, line_number + 1))
->
Found `print` at character 0 on line 1
Found `print` at character 9 on line 1
Found `print` at character 0 on line 3
Found `print` at character 9 on line 3
Found `print` at character 23 on line 3
strings already have an index method to find substring, and you can give extra arguments to find the next copy of the next copy of a given subtring
>>> text = '''print is print as
it is the function an
print is print and not print
'''
>>> text.index("print")
0
>>> text.index("print",1)
9
>>> text.index("print",10)
40
>>> text.index("print",41)
49
>>> text.index("print",50)
63
>>> text.index("print",64)
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
text.index("print",64)
ValueError: substring not found
>>>
You can use regular expressions:
import re
text = '''print is print as
it is the function an
print is print and not print
'''
for i in re.finditer("print", text):
print(i.start())
# OR AS A LIST
[i.start() for i in re.finditer("print", text)]
You were on the right track initially. You split your text into lines. The next step is to split each line into words, not letters, using the split() method. You can then easily get the index of each 'print' string in each line.
The following code prints the desired indexes as list of lists, with each inner list corresponding to a separate line:
text = '''print is print as
it is the function an
print is print and not print
'''
index_list = []
for line in text.splitlines():
index_list.append([])
for idx, word in enumerate(line.split()):
if word == 'print':
index_list[-1].append(idx)
print(index_list)
#[[0, 2], [], [0, 2, 5]]

Spliting string without spaces

I am trying to find a way to split each letter in a word to a list.
I have tried to do this with a for letter in message add space but this hasn't worked.
message = 'hello'
for letter in message:
letter += ' '
message = message.split()
print(message)
I get
['hello']
I want
['h', 'e', 'l', 'l', 'o']
A string is an iterable. When iterating over a string, it yields each character individually. The list() constructor takes an iterable and creates a list out of its individual elements. So:
message = 'hello'
message = list(message)
print(message)
# ['h', 'e', 'l', 'l', 'o']
A string is already an array of charecters. Use list(str)
Example:
message = 'hello'
char_array = list(message)
print char_array

IndexError: string index out of range (enumerate) [duplicate]

This question already has answers here:
IndexError: string index out of range:
(5 answers)
Closed 2 years ago.
Okay so I have no idea what the problem is here. Everything I've read basically addresses the range not ending, thus the error, but that doesn't make sense to me since this is a fixed loop.
I'm simply trying to take a string, and throw each letter into a list one at a time. What am I missing?
>>> name = "Chris"
>>>
>>> my_list = []
>>>
>>> for key, value in enumerate(name):
... my_list.append(value[key])
... print (my_list)
...
The error I'm receiving:
['C']
Traceback (most recent call last):
File "<pyshell#7>", line 2, in <module>
my_list.append(value[key])
IndexError: string index out of range
What you are missing is that value is a single element string. Indexing at positions != 0 will result in an IndexError; during your first iteration that's what happens.
If you want to create it with your for loop, just append the value immediately:
for key, value in enumerate(name):
my_list.append(value)
Of course, enumerate is by no means required here, this can be simplified by calling list and supplying the string in question; Python will then create a list containing the contents of the string for you:
my_list = list(name)
For Python 3.x you can also unpack in a list literal with *:
my_list = [*name]
In all supplied snippets, the result of the operations is ['C', 'h', 'r', 'i', 's'] as required.
name = 'Chris'
my_list = list(name)
print(my_list)
Input: ['C', 'h', 'r', 'i', 's']
For one in each time:
for letter in name:
print(letter)
You are enumerating over a string ("Chris") which means that key and value will hold the following values during the iteration:
0 "C"
1 "h"
2 "r"
3 "i"
4 "s"
value[key] in the first iteration is ok, it returns 'C'.
In the second iteration, the index 1 is out of range for string "h".
What you probably want to do is this:
for i, value in enumerate(name):
my_list.append(value)
print (my_list)
An alternative way, to reach your goal:
>>>name ="Chris"
>>>list(name)
['C', 'h', 'r', 'i', 's']
For your example:
When iterating through a string in python, no enumeration is required.
>>>name = "Chris"
>>>my_list = []
>>>for i in name:
... my_list.append(i)
>>>my_list
['C', 'h', 'r', 'i', 's']
change my_list.append(value[key]) to my_list.append(value) in your code

Using .index() function in nested lists

I am trying to make a program that finds a certain value in a nested list, so I wrote this code:
list = [['S', 'T', 'U', 'T'], ['O', 'P', 'Q', 'R']]
However, when I inputted
list.index('O')
It gave me an error message saying
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
list.index('O')
ValueError: 'O' is not in list
Any ideas?
Well it is really simple, 'O' is not in the list, it only contains the other lists. Here is an example:
list_you_have = [['S', 'T', 'U', 'T'], ['O', 'P', 'Q', 'R']]
print list_you_have.index(['O','P','Q','R']) #outputs 1
Now if you do it like:
print list_you_have[1].index('O') # it outputs 0 because you're pointing to
#list which acctualy contains that 'O' char.
Now a function for nested char search would be
def nested_find(list_to_search,char):
for i, o in enumerate(list_to_search):
if char in o:
print "Char %s found at list %s at index %s" % (char, i, o.index(char))
Or maybe an even simpler solution as #zondo commented would be:
def nested_find(list_to_search,char):
newlist = sum(list_to_search, [])
if char in newlist:
print "Char %s is at position %s" % (char, newlist.index(char))
You can solve your problem in one-line:
print item in reduce(lambda x, y: x + y, nestedlists)

How to get all substrings in a list of characters (python)

I want to iterate over a list of characters
temp = ['h', 'e', 'l', 'l', 'o', '#', 'w', 'o', 'r', 'l', 'd']
so that I can obtain two strings, "hello" and "world"
My current way to do this is:
#temp is the name of the list
#temp2 is the starting index of the first alphabetical character found
for j in range(len(temp)):
if temp[j].isalpha() and temp[j-1] != '#':
temp2 = j
while (temp[temp2].isalpha() and temp2 < len(temp)-1:
temp2 += 1
print(temp[j:temp2+1])
j = temp2
The issue is that this prints out
['h', 'e', 'l', 'l', 'o']
['e', 'l', 'l', 'o']
['l', 'l', 'o']
['l', 'o']
['o']
etc. How can I print out only the full valid string?
Edit: I should have been more specific about what constitutes a "valid" string. A string is valid as long as all characters within it are either alphabetical or numerical. I didn't include the "isnumerical()" method within my check conditions because it isn't particularly relevant to the question.
If you want only hello and world and your words are always # seperated, you can easily do it by using join and split
>>> temp = ['h', 'e', 'l', 'l', 'o', '#', 'w', 'o', 'r', 'l', 'd']
>>> "".join(temp).split('#')
['hello', 'world']
Further more if you need to print the full valid string you need to
>>> t = "".join(temp).split('#')
>>> print(' '.join(t))
hello world
You can do it like this:
''.join(temp).split('#')
List has the method index which returns position of an element. You can use slicing to join the characters.
In [10]: temp = ['h', 'e', 'l', 'l', 'o', '#', 'w', 'o', 'r', 'l', 'd']
In [11]: pos = temp.index('#')
In [14]: ''.join(temp[:pos])
Out[14]: 'hello'
In [17]: ''.join(temp[pos+1:])
Out[17]: 'world'
An alternate, itertools-based solution:
>>> temp = ['h', 'e', 'l', 'l', 'o', '#', 'w', 'o', 'r', 'l', 'd']
>>> import itertools
>>> ["".join(str)
for isstr, str in itertools.groupby(temp, lambda c: c != '#')
if isstr]
['hello', 'world']
itertools.groupby is used to ... well ... group consecutive items depending if they are of not equal to #. The comprehension list will discard the sub-lists containing only # and join the non-# sub-lists.
The only advantage is that way, you don't have to build the full-string just to split it afterward. Probably only relevant if the string in really long.
If you just want alphas just use isalpha() replacing the # and any other non letters with a space and then split of you want a list of words:
print("".join(x if x.isalpha() else " " for x in temp).split())
If you want both words in a single string replace the # with a space and join using the conditional expression :
print("".join(x if x.isalpha() else " " for x in temp))
hello world
To do it using a loop like you own code just iterate over items and add to the output string is isalpha else add a space to the output:
out = ""
for s in temp:
if s.isalpha():
out += s
else:
out += " "
Using a loop to get a list of words:
words = []
out = ""
for s in temp:
if s.isalpha():
out += s
else:
words.append(out)
out = ""

Categories