Print elements of string multiple times based on position - python

I'm trying to print each element individually, which is fine but also repeat each element based on position eg. "abcd" = A-Bb-Ccc-Dddd etc
So my problems are making print statements print x times based off their position in the string. I've tried a few combinations using len and range but i often encounter errors because i'm using strings not ints.
Should i be using len and range here? I'd prefer if you guys didn't post finished code, just basically how to go about that specific problem (if possible) so i can still go about figuring it out myself.
user_string = input()
def accum(s):
for letter in s:
pos = s[0]
print(letter.title())
pos = s[0 + 1]
accum(user_string)

You can enumerate iterables (lists, strings, ranges, dictkeys, ...) - it provides the index and a value:
text = "abcdef"
for idx,c in enumerate(text):
print(idx,c)
Output:
(0, 'a')
(1, 'b')
(2, 'c')
(3, 'd')
(4, 'e')
(5, 'f')
You can use that to print something multiple times. The print command takes 2 optional parameters :
print("Bla","blubb", sep=" --->", end=" Kawumm\n")
Output:
Bla --->blubb Kawumm
that specify what is printed between outputs and on the end of output - you can specify an end="" - so you can continue printing on the same line.
Doku:
Print
Enumerate
Edit:
user_string = input()
def accum(s):
t = [] # list to store stuff into
for count, letter in enumerate(s):
total = letter.upper() + letter * (count) # 1st as Upper, rest as is
t.append(total) # add to list
print(*t, sep="-") # the * "unpacks" the list into its parts
accum(user_string)
Unpacking:
print( [1,2,3,4,5], sep=" +++ ") # its just 1 value to print, no sep needed
print(*[1,2,3,4,5], sep=" +++ ") # 5 values to print, sep needed
Output:
[1, 2, 3, 4, 5]
1 +++ 2 +++ 3 +++ 4 +++ 5

You could try having a counter that will increase by 1 as the loop traverses through the string. Then, within the loop that you currently have, have another for loop to loop the size of the counter. If you want it to print out the first letter capitalized then you will need to account for that along with the dashes.

Related

How can I store my result in tuple in Python

Write a function called word_freq(text) which takes one string
argument. This string will not have any punctuation. Perform a count
of the number of 'n' character words in this string and return a list
of tuples of the form[(n, count), (n-1, count) ...] in descending
order of the counts. For example:
Example: word_freq('a aaa a aaaa')
Result: [(4, 1), (3, 1), (1, 2)]
Note: that this does not show anything for the 2 character words. str1
= 'a aaa a aaa' str.split(str1) str.count(str1)
def word_freq(str): Python code to find frequency of each word
I tried this
text = 'a aaa a aaaa'
def word_freq(str):
tuple = ()
count = {}
for x in str:
if x in count.keys():
count[x] += 1
else:
count[x] = 1
print(count)
def count_letters(word):
char = "a"
count = 0
for c in word:
if char == c:
count += 1
return count
word_freq(text)
The code below does what you want. Now I'll explain how it works. before anything, we will make a dictionary called "WC" which will hold the count of each n-character-word in our sentence. now we start. first of all, it receives a string from user. then it takes the string and using split(), it turns the string into a LIST of words. then for each word it checks its length, if it is 2, it ignores it. otherwise, it will add 1 to the count of that n-character word in our dictionary.
after every word is checked, we use wc.items() to turn our dictionary into a list of tuples. Each element in the list is a tuple that contains data for each word. each tuple has 2 elements. the first is number of charatcers of each word and the second element is the number of times it existed in the sentence. with that out of the way, Now all we need is to do is sort this list based on the character counts in reverse (from high char count to low char count). we do that using the sorted function. we sort based on x[0] which means the first element of each tuple which is the character count for each word. Finally, we return this list of tuples. You can print it.
if anything is unclear, let me know. also, you can put print() statements at every line so you can better understand what is happening.
here's the code, I hope it helps:
inp = input("Enter your text: ")
def word_count(inp_str):
wc = {}
for item in inp_str.strip().split():
if len(item) == 2:
continue
wc[len(item)] = wc.get(len(item), 0) + 1
return sorted(wc.items(), key=lambda x: x[0], reverse = True)
print(word_count(inp))

Way to pass multiple parameters in a for loop?

My code:
seperated = startContent.split(' ')
seperatedNum = len(seperated)
#Ask for user input
for word in seperated and for i in seperatedNum:
if word == 'ADJECTIVE':
seperated[i] = input('Enter an adjective:')
elif word == 'NOUN':
seperated[i] = input('Enter a noun:')
elif word == 'ADVERB':
seperated[i] = input('Enter an adverb:')
elif word == 'VERB':
seperated[i] = input('Enter a verb:')
Basically asking the user input each time they run into one of the following words (there can be multiple of each).
I get my sentence, split it into a list with split command. And run the loop for each word. I want to then edit the list using list[x] = 'replacement' method.
The word in seperated, returns the listitem. So I need another argument passed to it, e.g i in len(list) to then get the accurate index of the word. I can't use list.index(str) because it returns the first index of the string when there are multiple iterations of the text.
You're looking for a way to pass multiple parameters in a for loop: There is nothing special about a for loop in this regard. The loop will iterate over a given sequence and will, each iteration, assign the current element to the given left-hand side.
for LEFT_HAND_SIDE in SEQUENCE
Python also supports "automatic" unpacking of sequences during assigments, as you can see in the following example:
>>> a, b = (4, 2)
>>> a
4
>>> b
2
In conclusion, you can just combine multiple variables on the left-hand side in your for loop with a sequence of sequences:
>>> for a, b in [(1, 2), (3, 4)]:
... print(a)
... print(b)
...
1
2
3
4
That for loop had two assignments a, b = (1, 2) and a, b = (3, 4).
In you specific case, you want to combine the value of an element in a sequence with its index. The built-in function enumerate comes in handy here:
>>> enumerate(["x", "y"])
<enumerate object at 0x7fc72f6685a0>
>>> list(enumerate(["x", "y"]))
[(0, 'x'), (1, 'y')]
So you could write your for loop like this:
for i, word in enumerate(seperated)

Increasing understanding of printing multiple variables [duplicate]

for example in this code below the with the end the integers stay on the same line but without the it does not.
num = 5
for i in range(1, num +1):
for j in range(num, i-1, -1):
print(j, end="")
print()
The end statement for printing in Python allows the programmer to define a custom ending character for each print call other than the default \n
For instance, if you have a function that is to print all values within a list on the same line, you do:
def value(l):
for items in l:
print(l, end=' ')
So if the list argued to this function contains the values [1, 2, 3, 4], it will print them in this manner: 1 2 3 4. If this new ending character parameter was not defined they would be printed:
1
2
3
4
The same principle applies for ANY value you provide for the end option.
In Python 3, the default ist end='\n' for the print function which is a newline after the string is printed.
To suppress this newline, one can set end='' so that the next print starts in the same line.
This is unrelated to the for loop.

Convert decimal to Roman numerals

d_hsp={"1":"I","2":"II","3":"III","4":"IV","5":"V","6":"VI","7":"VII","8":"VIII",
"9":"IX","10":"X","11":"XI","12":"XII","13":"XIII","14":"XIV","15":"XV",
"16":"XVI","17":"XVII","18":"XVIII","19":"XIX","20":"XX","21":"XXI",
"22":"XXII","23":"XXIII","24":"XXIV","25":"XXV"}
HSP_OLD['tryl'] = HSP_OLD['tryl'].replace(d_hsp, regex=True)
HSP_OLD is a dataframe, tryl is one column of HSP_OLD, and here's some example of values in tryl:
SAF/HSP: Secondary diagnosis E code 1
SAF/HSP: Secondary diagnosis E code 11
I use a dictionary to replace, it works for 1-10, but for 11, it will become "II" , for 12, it will become "III".
Sorry, didn't notice that you're not merely updating the field but you actually want to replace a number at the end, but even if that's the case - it's much better to properly convert your number to roman numerals than to map every possible occurrence of such (what would happen with your code if there is a number larger than 25?). So, here's one way to do it:
ROMAN_MAP = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'),
(50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]
def romanize(data):
if not data or not isinstance(data, str): # we know how to work with strings only
return data
data = data.rstrip() # remove potential extra whitespace at the end
space_pos = data.rfind(" ") # find the last space before the number
if space_pos != -1:
try:
number = int(data[space_pos + 1:]) # get the number at the end
roman_number = ""
for i, r in ROMAN_MAP: # loop-reduce substitution based on the ROMAN_MAP
while number >= i:
roman_number += r
number -= i
return data[:space_pos + 1] + roman_number # put everything back together
except (TypeError, ValueError):
pass # couldn't extract a number
return data
So now if we create your data frame as:
HSP_OLD = pd.DataFrame({"tryl": ["SAF/HSP: Secondary diagnosis E code 1",
None,
"SAF/HSP: Secondary diagnosis E code 11",
"Something else without a number at the end"]})
We can noe easily apply our function over the whole column with:
HSP_OLD['tryl'] = HSP_OLD['tryl'].apply(romanize)
Which results in:
tryl
0 SAF/HSP: Secondary diagnosis E code I
1 None
2 SAF/HSP: Secondary diagnosis E code XI
3 Something else without a number at the end
Of course, you can adapt the romanize() function to your needs to search any number within your string and turn it to roman numerals - this is just an example for how to quickly find the number at the end of the string.
You need to keep the order of the items, and start searching with the longest substring.
You may use an OrderDict here. To initialize it, use a list of tuples. You may reverse it already here, when initializing, but you can do it later, too.
import collections
import pandas as pd
# My test data
HSP_OLD = pd.DataFrame({'tryl':['1. Text', '11. New Text', '25. More here']})
d_hsp_lst=[("1","I"),("2","II"),("3","III"),("4","IV"),("5","V"),("6","VI"),("7","VII"),("8","VIII"), ("9","IX"),("10","X"),("11","XI"),("12","XII"),("13","XIII"),("14","XIV"),("15","XV"), ("16","XVI"),("17","XVII"),("18","XVIII"),("19","XIX"),("20","XX"),("21","XXI"), ("22","XXII"),("23","XXIII"),("24","XXIV"),("25","XXV")]
d_hsp = collections.OrderedDict(d_hsp_lst) # Creating the OrderedDict
d_hsp = collections.OrderedDict(reversed(d_hsp.items())) # Here, reversing
>>> HSP_OLD['tryl'] = HSP_OLD['tryl'].replace(d_hsp, regex=True)
>>> HSP_OLD
tryl
0 I. Text
1 XI. New Text
2 XXV. More here

index of second repeated character in a string

I am trying a hangman code in python. For matching a character of a word , iam using index function to get the location of character.
Ex :word = 'COMPUTER'
user_input = raw_input('Enter a character :') # say 'T; is given here
if user_input in word:
print "\nThe Character %c is present in the word \n" %user_input
word_dict[word.index(user_input)] = user_input
#so the output will looks like
{0: '_', 1: '_', 2: '_', 3: '_', 4: '_', 5: 'T', 6: '_', 7: '_'}
Now , my problems comes when it comes with the repeated character.
# Another example
>>> 'CARTOON'.index('O')
4
For the second 'O', how to get its index. since i have used this 'index' logic, i am looking to continue on this way.
As per the str.index docs, signature looks like this
str.index(sub[, start[, end]])
The second parameter is the starting index to search from. So you can pass the index which you got for the first item + 1, to get the next index.
i = 'CARTOON'.index('O')
print 'CARTOON'.index('O', i + 1)
Output
5
The above code can be written like this
data = 'CARTOON'
print data.index('O', data.index('O') + 1)
You can even have this as a utility function, like this
def get_second_index(input_string, sub_string):
return input_string.index(sub_string, input_string.index(sub_string) + 1)
print get_second_index("CARTOON", "O")
Note: If the string is not found atleast twice, this will throw ValueError.
The more generalized way,
def get_index(input_string, sub_string, ordinal):
current = -1
for i in range(ordinal):
current = input_string.index(sub_string, current + 1)
else:
raise ValueError("ordinal {} - is invalid".format(ordinal))
return current
print get_index("AAABBBCCCC", "C", 4)
A perhaps more pythonic method would be to use a generator, thus avoiding the intermediate array 'found':
def find_indices_of(char, in_string):
index = -1
while True:
index = in_string.find(char, index + 1)
if index == -1:
break
yield index
for i in find_indices_of('x', 'axccxx'):
print i
1
4
5
An alternative would be the enumerate built-in
def find_indices_of_via_enumerate(char, in_string):
return (index for index, c in enumerate(in_string) if char == c)
This also uses a generator.
I then got curious as to perf differences. I'm a year into using python, so I'm only beginning to feel truly knowledgeable. Here's a quick test, with various types of data:
test_cases = [
('x', ''),
('x', 'axxxxxxxxxxxx'),
('x', 'abcdefghijklmnopqrstuvw_yz'),
('x', 'abcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvwxyz'),
]
for test_case in test_cases:
print "('{}', '{}')".format(*test_case)
print "string.find:", timeit.repeat(
"[i for i in find_indices_of('{}', '{}')]".format(*test_case),
"from __main__ import find_indices_of",
)
print "enumerate :", timeit.repeat(
"[i for i in find_indices_of_via_enumerate('{}', '{}')]".format(*test_case),
"from __main__ import find_indices_of_via_enumerate",
)
print
Which, on my machine results in these timings:
('x', '')
string.find: [0.6248660087585449, 0.6235580444335938, 0.6264920234680176]
enumerate : [0.9158611297607422, 0.9153609275817871, 0.9118690490722656]
('x', 'axxxxxxxxxxxx')
string.find: [6.01502799987793, 6.077538013458252, 5.997750997543335]
enumerate : [3.595151901245117, 3.5859270095825195, 3.597352981567383]
('x', 'abcdefghijklmnopqrstuvw_yz')
string.find: [0.6462750434875488, 0.6512351036071777, 0.6495819091796875]
enumerate : [2.6581480503082275, 2.6216518878936768, 2.6187551021575928]
('x', 'abcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvw_yzabcdefghijklmnopqrstuvwxyz')
string.find: [1.2539417743682861, 1.2511990070343018, 1.2702908515930176]
enumerate : [7.837890863418579, 7.791800022125244, 7.9181809425354]
enumerate() method is more expressive, pythonic. Whether or not perf differences matter depends on the actual use cases.
You've asked how to find the second occurrence, and gotten an excellent answer for that, generalized for any specific occurrence. What you'll realize you actually want though is all occurrences at once. Here's a method for that:
def find_characters(word, character):
found = []
last_index = -1
while True:
try:
last_index = word.index(character, last_index+1)
except ValueError:
break
else:
found.append(last_index)
return found
You can use the count method of the strings to find the number of occurrences of the user_input in the string. Then, use the str.index(sub,start) method for each occurrence of the user_input in the word and increment start by 1 each time so that you do not wind up getting the same index each time.
if user_input in word:
count=word.count(user_input)
a=word.index(user_input)
word_dict[word.index(a)]=user_input
for i in range(count-1):
a=word.index(user_input,a+1)
word_dict[word.index(a)]=user_input
This should really be a one-liner if you use filter because if you use index you will be forced to either iterate or use recursion. In this case, there is absolutely no need for either. You can just filter out the values that are relevant to you.
Using filter is easy. An example implementation is the following one-liner:
def f1(w, c):
return zip(* filter(lambda (x,y): x == c, zip(w, range(len(w))) ))[1]
f1('cartoon', 'o') # --> (4, 5)
You can always add error checking as in:
def f1(w, c) :
if c not in w: return ()
else: return zip(* filter(lambda (x,y): x == c, zip(w, range(len(w))) ))[1]
If the character isn't found in the string, you just get an empty tuple. Otherwise, you get all elements that match. If you want something generic, counting on the fact that there will only be one or two instances of a character is not the right way to go about it. For example:
In [18]: f1('supercalifragilisticexpialidocious', 'i')
Out[18]: (8, 13, 15, 18, 23, 26, 30)
Here is another Example.
a="samesame"
po=-1 # for this, po+1 is start from 0
for c in a:
if c=='s': # For example, I chose "S" what I want to find
po = a.index(c,po+1) # if you find first element 'C' then search again in next postion
print(po)
Apologies if this answer is not properly formatted or I've messed up somewhere as I am new here and this is my first post. I have used the following code in my own Hangman games to get the index of multiple repeating letters in a word and has worked great. Hopefully a newcomer will understand this ok.
a = "hangman" #the chosen word
length = len(a) #determines length of chosen word
for i in range(length) #this will loop through the code length number of times
if a[i] == "n": #n is the players guess. Checks if the letter is at index i
po = a.index("n", i) # po gets the index of the letter if previous line is true
print(po) #prints the position/s
Hope this helps someone!
def findcharpos(string, character, position=None):
array = []
index = -1
while True:
try:
index = string.index(character, index+1)
except ValueError:
break
else:
array.append(index)
if position == None and len(array) != 0:
return array
elif position > len(array):
raise ValueError(f"The character {character} does not occur {position}
times in the {string}")
else:
return array[position-1]
return array
msg = 'samesame'
print(msg.index('s', 2)) # prints the index of second 's' in the string.

Categories