Add a character to a string in multiple positions in Python 3 - python

Python beginner here, sorry if this is a dumb question.
So I have a long string, and I need to add a character in very specific areas of the strings. For example, a | after character number 23, 912, and 1200. I read this Add string in a certain position in Python, but it only works for adding one character.
Also, the solution needs to be expandable, not just do it 3 times. The code I'm making can have lots of different locations with where I want the character to be.

With reference to the link that you posted Add string in a certain position in Python;
If you would like to repeat the operation for different values, you could create a list containing all index positions where you would like your | character to be inserted.
For example,
>>> l = [1, 3, 4]
>>> s = "abcdef"
>>> for i in l:
>>> s = s[:i] + "|" + s[i:] # as suggested in your link
>>> s
'a|b||cdef'
This will allow you to repeat the process for the set of values that you provide in the list. You could also define a function to assist in this, which I could explain if this method is insufficient!
Note, however, that this will insert the character relative to the current iteration. That is, in this example, after adding the | at position 1, the next insert position, 3, is different from what it was before the first insert. You could avoid this (if you want) by including a counter variable to offset all the index positions by the number of inserts that have been executed (will require initial list to be ordered).

Not so good at python, hope I can help
According to that site you went to, you can make a while loop to solve the problem
The code should look something like this
def insert_dash(string, index, addin):
return string[:index] + addin + string[index:]
alldone = False
string = input("String: ")
index = " "
while index:
index = input("Index: ")
addin = input("Add into: ")
string = insert_dash(string, index, addin)
Hope it helps!
PS: I have NOT tried the code, but I think it will work

Related

Trying to sort two combined strings alphabetically without duplicates

Challenge: Take 2 strings s1 and s2 including only letters from a to z. Return a new sorted string, the longest possible, containing distinct letters - each taken only once - coming from s1 or s2.
# Examples
a = "xyaabbbccccdefww"
b = "xxxxyyyyabklmopq"
assert longest(a, b) == "abcdefklmopqwxy"
a = "abcdefghijklmnopqrstuvwxyz"
assert longest(a, a) == "abcdefghijklmnopqrstuvwxyz"
So I am just starting to learn, but so far I have this:
def longest(a1, a2):
for letter in max(a1, a2):
return ''.join(sorted(a1+a2))
which returns all the letters but I am trying to filter out the duplicates.
This is my first time on stack overflow so please forgive anything I did wrong. I am trying to figure all this out.
I also do not know how to indent in the code section if anyone could help with that.
You have two options here. The first is the answer you want and the second is an alternative method
To filter out duplicates, you can make a blank string, and then go through the returned string. For each character, if the character is already in the string, move onto the next otherwise add it
out = ""
for i in returned_string:
if i not in out:
out += i
return out
This would be empedded inside a function
The second option you have is to use Pythons sets. For what you want to do you can consider them as lists with no dulicate elements in them. You could simplify your function to
def longest(a: str, b: str):
return "".join(set(a).union(set(b)))
This makes a set from all the characters in a, and then another one with all the characters in b. It then "joins" them together (union) and you get another set. You can them join all the characters together in this final set to get your string. Hope this helps

Is it possible to hard declare a variable in Python?

I am trying to use a variable inside a substructure. I guess the variable should be of integer data type, and I am trying to add a loop here but it my data type is list since it contains multiple integers.
INV_match_id = [['3749052'],['3749522']]
from statsbombpy import sb
for x in range(2):
match=INV_match_id[x]
match_db = sb.events(match_id=match)
print(match)
I have tried to extract the data one by one using another variable, but still it got declared as list. Whenever I give direct values to "match" it works. for eg: if I add a line match=12546 the substructure takes the value properly.
Next thing I want to try is hard declare "match" variable as integer. Any input is appreciated. I am pretty new to Python.
Edit: Adding this solution from #quamrana here.
"So, to answer your original question: Is it possible to hard declare a variable in Python?, the answer is No. Variables in python are just references to objects. Objects can be of whatever type they want to be."
You said: " I want to loop and take the numbers one by one."
Did you mean this:
for match in INV_match_id:
match_db = sb.events(match_id=match)
I don't know what you want to do with match_db
Update:
"that single number is also declared as a list. like this- ['125364']"
Well if match == ['125364'] then it depends on whether you want: "125364" or 125364. I assume the latter since you talk a lot about integers:
for match in INV_match_id:
match = int(match[0])
match_db = sb.events(match_id=match)
Next Update:
So you have: INV_match_id = ['3749052','3749522']
This means that the list is a list of strings, so the code changes to this:
for match in INV_match_id:
match_db = sb.events(match_id=int(match))
Your original code was making match into a list of the digits of each number. (eg match = [1,2,5,3,6,4])
Reversionary Update:
This time we have: INV_match_id = [['3749052'],['3749522']]
that just means going back to the second version of my code above:
for match in INV_match_id:
match = int(match[0])
match_db = sb.events(match_id=match)
It's as simple as:
from statsbombpy import sb
INV_match_id = [['3749052'],['3749522']]
for e in INV_match_id:
match_db = sb.events(match_id=e[0])
print(match_db)
You have a list of lists albeit that the sub-lists only contain one item.
match_id can be either a string or int

How do I loop through the same lists multiple times?

Please bear with me, I have been using Python for only 2 weeks.
I am writing a small project which includes using a user defined key to scramble a text file (string).
Example:
String = "Monty"
Key = 1232
The first thing I do is split it into letters so they become:
['m','o','n','t','y'] (all letters are lowercased)
['1','2','3','2']
Easy enough so far for me.
I also have a list which has all english letters and numbers from 0-9.
Now, the scrambling part looks like this:
def encrypt0r(textList,keyList,letterList): #Encrypting the string using the key
encryptedList = []
encryptedStr = ""
for character in textList:
if character in letterList:
tempIndex = letterList.index(character) + 1 #THE 1 IS A PLACEHOLDER
encryptedList.append(letterList[tempIndex])
else:
encryptedList.append(character)
encryptedStr = "".join(encryptedList)
return encryptedStr
where the 3 lists are my list of letters, the list of 4 digits and list of all english letters and nums respectively.
The output of monty should be like so:
nqqvz
because:
index of m + 1 = n
index of o + 2 = q
index of n + 3 = q
index of t + 2 = v
index of y + 1 = z **Note how when the keyList is already over, it goes back to the start of the keyList. How can I make it go through the list then once it does so once, go through it again.
If there is a faster way with the steps, I would love to hear it. I keep getting these godsent images of [0::4] - [3::4] in my head but I have no idea how to implement it.
My second problem is similar to my first:
The placeholder in the above code is just to check if my program actually works without the user defined key. And it does, unless you tell it to go past the letterlist. The list ends at [......,'8','9'], so 8 + 1 will be scrambled as 9 but I want 9 + 1 to go BACK to the start of this same list back and scramble the 9 as an "a". I've been scouring the internet for 2 days and i finally caved in to posting here.
Thanks in advance for your help. Just asking you guys to keep the jargon/lingo a little more understandable to whats essentially a script kiddie (me), and if you have a solution, explain to me how it works so that I may learn and use it in a future project!
Part 1
Every letter in the input is coupled to an element in the key list. This means this is a job for zip (izip in python 2):
for character, key in zip(textList, keyList):
# processing
The problem is that if keyList is shorter than textList, it will stop at the end of keyList. However, there is a nice tool in itertools just for this: itertools.cycle:
for character, key in zip(textList, itertools.cycle(keyList)):
# processing
Part 2
If the index to get is greater than the length of the letterList, you want to start again from the front. This means the index to get is the modulo of the index and the length of the list:
encryptedList.append(letterList[tempIndex % len(letterList)])
Looking up an index has worst case complexity O(n), meaning it will look at every element in the list, if the wanted element is at the end. To make these lookups a lot faster, build a dictionary of the keys before you start and look up the indices in that (O(1) complexity):
lettermap = {letter: i for i, letter in enumerate(letterList)}
And then in your loop:
if character in lettermap:
tempIndex = lettermap[character]
All together
def encrypt0r(text, keys, letters):
encrypted = []
lettermap = {letter: i for i, letter in enumerate(letters)}
for character, key in zip(text, itertools.cycle(keys)):
if character in lettermap:
new_index = lettermap[character] + key
encrypted.append(letters[new_index%len(letters)])
else:
encrypted.append(character)
return "".join(encrypted)

How do I right justify string in Python 3 not counting the string itself?

Just started learning python. And it looks to me that rjust() method is counting string that I'm trying to justify in justifying length.
Let me clarify a little bit, the book I'm using to study python had this type of small program:
order = "First\nSecond\nThird"
print("The order is: ", order)
Whose output is:
The order is: First
Second
Third
And I thought what could I change to make output as (desired output),
The order is: First
Second
Third
Well there may be very easy way to solve this but bear in mind I just started learning python. I tried formatting to no avail. After learning about list I came up with this solution,
order = "First\nSecond\nThird"
listed_order = order.split("\n")
length_of_list = len(listed_order)
print_line = "The order is: "
length = len(print_line)
print(print_line + listed_order[0])
for i in range(1, length_of_list):
print(listed_order[i].rjust(length))
But the output is,
The order is: First
Second
Third
That means rjust() method is counting Second and Third to make justified length of 14, while I wanted them to start from 14. Second has 8 spaces in front of it to make justified length of 14, while Third has 9 spaces.
So, what can I do to get my desired output? If there is another way to solve this let me know.
What you describe is left-justified, but with an additional offset (also known as indentation).
Instead of
print(listed_order[i].rjust(length))
simply do
print(' ' * length + listed_order[i])
If there is nothing to the right of listed_order[i], you don't need to use ljust either.
You might want to take a look at textwrap.indent, which lets you indent whole blocks of text without splitting the lines manually.
You don't have to do such things: length_of_list = len(listed_order). You can run your loop without checking length of the list:
for i in listed_order:
print(i.rjust(length))
EDIT:
As pointed in the comments, this would also print first element which we want to skip. You can do it by telling python to process from second element by adding [1:], which means from element of index 1 (which is second after index 0) untill end), so:
for i in listed_order[1:]:
print(i.ljust(length))
Now to the core.
What you need is the number of whitespaces. You can get it by running this:
number_of_whitespaces = len("The order is: ")
And then print it out before each line:
print(' ' * number_of_whitespaces, end='')
Full solution here:
#!/usr/bin/env python3
order = "First\nSecond\nThird"
print("The order is: ", order)
orders = order.split()
whitespaces = len('The order is: ')
print('The order is: {}'.format(orders[0]))
for o in orders[1:]:
print(' ' * whitespaces, end='')
print(o)
EDIT2: Added missing colon, Changed rjust to ljust
EDIT3: Added full solution

comparing occurrence of strings in list in python

i'm super duper new in python. I'm kinda stuck for one of my class exercises.
The question goes something like this: You have a file that contains characters i.e. words. (I'm still at the stage where all the terms get mixed up, I apologize if that is not the correct term)
Example of the file.txt content: accbd
The question asks me to import the file to python editor and make sure that no letter occurs more than letter that comes later than it in the alphabet. e.g. a cannot occur more frequently than b; b cannot occur more than c, and so on. In the example file, c occurs more frequently than d, so I need to raise an error message.
Here's my pathetic attempt :
def main():
f=open('.txt','r') # 1st import the file and open it.
data = f.read() #2nd read the file
words = list(data) #3rd create a list that contains every letter
newwords = sorted(words) # sort according to alphabetical order
I'm stuck at the last part which is to count that the former word doesn't occur more than the later word, and so on. I tried two ways but neither is working. Here's trial 1:
from collections import counter
for i in newwords:
try:
if counter(i) <=counter(i+1):
print 'ok'
else:
print 'not ok between indexes %d and %d' % (i, i+1)
except:
pass
The 2nd trial is similar
for i in newwords:
try:
if newwords.count(i) <= newwords.count(i+1):
print 'ok'
else:
print 'ok between indexes %d and %d' % (i, i+1)
except:
pass
What is the correct way to compare the count for each word in sequential order?
I had posted an answer, but I see it's for an assignment, so I'll try to explain instead of just splatting a solution here.
My suggestion would be to solve it in three steps:
1) in the first line, create a list of sorted characters that appear in the string:
from the data string you can use set(data) to pick every unique character
if you use sort() on this set you can create a list of characters, sorted alphabetically.
2) then use this list in a for loop (or list comprehension) to create a second list, of their number of occurrences in data, using data.count(<letter in the list>); note that the elements in this second list are technically sorted based on the alphabetical order of the letters in the first list you made (because of the for loop).
3) compare this second list of values with a sorted version of itself (now sorted by values), and see if they match or not. If they don't match, it's because some of the initial letters appears too many times compared to the next ones.
To be a little more clear:
In [2]: string = 'accbd'
In [3]: import collections
In [4]: collections.Counter(string)
Out[4]: Counter({'c': 2, 'a': 1, 'b': 1, 'd': 1})
Then it's just a for loop with enumerate(list_).

Categories

Resources