For example, if I entered I love dogs, it would need to look like this:
I l o v e d o g s
This code does not do what I need it to do:
def spaceitout(source):
pile = ""
for letter in source:
pile = pile+letter
print pile
print pile
Simple answer would be:
def spaceitout(source):
pile = ""
for letter in source:
pile = pile + letter + " "
pile = pile[:-1] #Strip last extraneous space.
print pile
def evenly_spaced(string_,space_= 1):
import re
return (' '*space_).join([c for c in re.split(r'(\w)',string_) if c.isalpha()])
print(evenly_spaced(" This a long story ",2))
T h i s a l o n g s t o r y
Spaces between letters:
def spaceitout(source, count):
return (' '*count).join([letter for letter in source.replace(' ','')])
Spaces between words:
def spaceitout(source, count):
return (' '*count).join(source.split())
Spaces between all chars:
def spaceitout(source, count):
return (''.join([c + (' '*count) for c in source]).strip())
Allows you to specify spaces between words, and spaces between characters. Based on the answers provided by BigOldTree
def space_it(text, word_space=1, char_space=0):
return (' '*word_space).join([(' '*char_space).join(x) for x in text.split(' ')])
Note: This will treat two spaces in the input text as having an "invisible word" between them, change text.split(' ') to text.split() if this isn't desired.
Does this do what you need?
pile = ' '.join(source)
This takes the elements of "source" and joins them with a single space as the connector.
If you need only the letters separated, then build the list of letters only, and join that:
pile = ' '.join([c for c in source if c.isalpha()])
i think that this is what you was looking for:
line = 'I love dogs'
for i in line:
if i != ' ':
print i,
else:
print '',
using itertools:
import itertools
def space_word(word, spaces_count=1):
if spaces_count < 1:
raise ValueError("spaces_count < 1")
def space_word_wrapped(word, spaces_count):
letters = itertools.chain.from_iterable(zip(word, itertools.cycle(" ")))
skipped = 0 # have to keep track of how many letter skips
# or else from_word starts breaking!
# TODO : better implementation of this
for i, lett in enumerate(letters, start=1):
from_word = (i + skipped) % 2
if lett.isspace() and from_word:
if spaces_count == 1:
next(letters)
skipped += 1
continue # and skip the space itself
elif spaces_count == 2:
continue # just count the space
elif spaces_count == 3:
pass # count everything
else: # spaces_count >= 4
yield from [" "] * (spaces_count - 3)
yield lett
return ''.join(space_word_wrapped(word, spaces_count)).rstrip()
It's probably cheaper to just use an iterator here, but I like the generator in a nested function approach. So sue me! :)
This lists your word( 'his' = ['h','i','s'] and then joins it with a space instead of a comma.
def space(word):
return ' '.join(list(word))
Related
I am writing a program where the user enters certain substrings, and the code will concatenate them based on overlapping characters. The program works perfectly fine for two strings, however, when I enter three strings, it overlaps two substrings in the string.
Here is my code:
`
y = int(input("How many strings do you want to enter?: "))
String_List = []
final_str = ""
for i in range(y):
x = input("Enter a string: ")
String_List.append(x)
for o in String_List:
for p in String_List:
if o != p:
if o in p:
if p not in final_str:
final_str += str(p)
elif p in o:
if o not in final_str:
final_str += str(o)
for n in range(2,len(p)):
if o[-n:] == p[:n]:
if o and p not in final_str:
p = p[n:]
final_str += str(o+p)
for j in range(2,len(p)):
if o[:j] == p[-j:]:
if o and p not in final_str:
o = o[j:]
final_str += str(p+o)
else:
continue
else:
continue
print(final_str)
`
To better explain this problem, I entered three substrings, A1B2, 1B2C3, C3D4E5. Here is the output I got:
A1B2C31B2C3D4E5
The bold area is the repeat that I don't want.
Assuming you want to join successive strings on a common start/end.
merging on the shortest (non-null) match:
strings = ['A1B2', '1B2C3', 'C3D4E5']
out = strings[0]
for s in strings[1:]:
for i in range(1, min(len(out), len(s))):
if out[-i:] == s[:i]:
out += s[i:]
break
Output:
A1B2C3D4E5
merging on the longest match:
strings = ['A1B2', '1B2C3C3', 'C3C3D4E5'] # note the duplicated C3C3
out = strings[0]
for s in strings[1:]:
for i in range(min(len(out), len(s)), 1, -1):
if out[-i:] == s[:i]:
out += s[i:]
break
Output: A1B2C3C3D4E5
handling non matches
I'm adding a space for clarity
strings = ['A1B2', '1B2C3', 'C3D4E5', 'F6G7', 'G7H8']
out = strings[0]
for s in strings[1:]:
for i in range(min(len(out), len(s)), 1, -1):
if out[-i:] == s[:i]:
out += s[i:]
break
else:
out += ' ' + s
Output: A1B2C3D4E5 F6G7H8
Your code is so much complex to understand... I understand your goal you can solve this solution even with simpler solution.
import re
n= input("how many ")
fs = ''
for i in range(int(n)):
s= input(f"enter string{i+1} : ")
fs += s
print(re.sub(r"(.+?)\1+", r"\1", fs))
Obsorvations
input:
how many 3
enter string 1: A1B2
enter string 2: 1B2C3
enter string 3: C3D4E5
output
A1B2C3D4E5
I woud need assistance to find the best pythonic way to merge consecutive upper case characters in a string python
Example:
Input: You can pay N O W or Pay me Back MY Money later
Output: You can pay NOW or Pay me Back MY Money later
I am going with a very quick & dirty approach temporarily
s='lets P A Y N O W'
new_s = s
replace_maps = []
replace_str = ''
prev_cap = False
for i, c in enumerate(s):
if c == ' ':
continue
if c.isupper():
if prev_cap:
replace_str += c
else:
start = i
replace_str = c
prev_cap = True
else:
end = i
if prev_cap:
replace_maps.append([start, end, replace_str])
prev_cap = False
replace_str = ''
else:
end = i
if prev_cap:
replace_maps.append([start, end, replace_str])
prev_cap = False
replace_str = ''
new_s = s[:replace_maps[0][0]] + replace_maps[0][2] + s[replace_maps[0][1]:]
new_s
Output: lets PAYNOWW
The best idea is to use Look-aheads ?= and Look-behinds ?<= and check for Upper case letters.
for more info on regex
this regex should make the job
import re
data = "I could not find a C O V I D patient in the hospital."
re.sub(r"(?<=[A-Z])\s(?=[A-Z])", r'', data)
'I could not find a COVID patient in the hospital.'
EDIT
Regarding your new input after question modification
data = "You can pay N O W or Pay me Back MY Money later"
re.sub(r"(?<=[A-Z])\s(?=[A-Z] )", r'', data)
output
'You can pay NOW or Pay me Back MY Money later'
without regex:
mystring = mystring.split(" ")
res = mystring[0]
for i in range(1, len(mystring)):
if not (mystring[i-1].isupper() and mystring[i].isupper()):
res+= " "
res += mystring[i]
I don't know what the most pythonic way could be. I can only tell you what I came up.
import re
def merge_cons_up(string):
pattern = re.compile(" [A-Z](?![a-zA-Z0-9_.-])")
sub_text = re.findall(pattern=pattern, string=string)
repl = "".join(sub_text).replace(" ", "")
sub = re.sub(pattern=pattern, string=string, repl=" " + repl, count=1)
final_string = re.sub(pattern=pattern, string=sub, repl="")
return final_string
print(merge_cons_up("I could not find a C O V I D patient in the hospital."))
Output:
I could not find a COVID patient in the hospital.
Here is what I have so far:
def reversestring(thestring):
words = thestring.split(' ')
rev = ' '.join(reversed(words))
return rev
stringing = input('enter string: ')
print(reversestring(stringing))
I know I'm missing something because I need the punctuation to also follow the logic.
So let's say the user puts in Do or do not, there is no try.. The result should be coming out as .try no is there , not do or Do, but I only get try. no is there not, do or Do. I use a straightforward implementation which reverse all the characters in the string, then do something where it checks all the words and reverses the characters again but only to the ones with ASCII values of letters.
Try this (explanation in comments of code):
s = "Do or do not, there is no try."
o = []
for w in s.split(" "):
puncts = [".", ",", "!"] # change according to needs
for c in puncts:
# if a punctuation mark is in the word, take the punctuation and add it to the rest of the word, in the beginning
if c in w:
w = c + w[:-1] # w[:-1] gets everthing before the last char
o.append(w)
o = reversed(o) # reversing list to reverse sentence
print(" ".join(o)) # printing it as sentence
#output: .try no is there ,not do or Do
Your code does exactly what it should, splitting on space doesn't separator a dot ro comma from a word.
I'd suggest you use re.findall to get all words, and all punctation that interest you
import re
def reversestring(thestring):
words = re.findall(r"\w+|[.,]", thestring)
rev = ' '.join(reversed(words))
return rev
reversestring("Do or do not, there is no try.") # ". try no is there , not do or Do"
You can use regular expressions to parse the sentence into a list of words and a list of separators, then reverse the word list and combine them together to form the desired string. A solution to your problem would look something like this:
import re
def reverse_it(s):
t = "" # result, empty string
words = re.findall(r'(\w+)', s) # just the words
not_s = re.findall(r'(\W+)', s) # everything else
j = len(words)
k = len(not_s)
words.reverse() # reverse the order of word list
if re.match(r'(\w+)', s): # begins with a word
for i in range(k):
t += words[i] + not_s[i]
if j > k: # and ends with a word
t += words[k]
else: # begins with punctuation
for i in range(j):
t += not_s[i] + words[i]
if k > j: # ends with punctuation
t += not_s[j]
return t #result
def check_reverse(p):
q = reverse_it(p)
print("\"%s\", \"%s\"" % (p, q) )
check_reverse('Do or do not, there is no try.')
Output
"Do or do not, there is no try.", "try no is there, not do or Do."
It is not a very elegant solution but sure does work!
Asked my friend to give me an assignment for me to practice. It is:
If a user enters a string "AAABNNNNNNDJSSSJENDDKEW" the program will return
"3AB6NDJ2SJEN2DKEW" and vice versa.
This what I tried so far:
from collections import Counter
list_user_input =[]
list_converted_output=[]
current_char = 0 #specifies the char it is reading
next_char = 1
cycle = 0 # counts number of loops
char_repeat = 1
prev_char=""
count = 1
user_input = input("Enter your string: ")
user_input_strip = user_input.strip()
user_input_striped_replace = user_input_strip.replace(" ", "").lower()
list_user_input.append(user_input_striped_replace[0:len(user_input_striped_replace)])
print(list_user_input)
print(user_input_striped_replace)
I have "cleaned" the code so it removes white spaces and keeps it in low cap
Here is where I am stuck - the logics. I was thinking to go the through the string one index at a time and compare the next on to the other. Is this the wright way to go about it? And I'm not even sure about the loop construction.
#counter = Counter(list_user_input)
#print(counter)
#while cycle <= len(user_input_striped_replace):
for letter in user_input_striped_replace:
cycle+=1
print("index nr {}, letter: ".format(current_char)+letter +" and cycle : " + str(cycle))
current_char+=1
if letter[0:1] == letter[1:2]:
print("match")
print("index nr {}, letter: ".format(current_char)+letter +" and cycle : " + str(cycle))
current_char+=1
Counter is a good choice for such task but about the rest you can use sorted to sort the items of Counter then use a list comprehension to create the desire list then concatenate with join :
>>> from collections import Counter
>>> c=Counter(s)
>>> sor=sorted(c.items(),key=lambda x:s.index(x[0]))
>>> ''.join([i if j==1 else '{}{}'.format(j,i) for i,j in sor])
'3AB7N3D2J3S2EKW'
I'd do it with regular expressions. Have a look at those.
Spoiler:
import re
def encode(s):
return re.sub(r'(.)\1+', lambda m: str(len(m.group(0)))+m.group(1), s)
def decode(e):
return re.sub('(\d+)(.)', lambda m: int(m.group(1))*m.group(2), e)
s = "AAABNNNNNNDJSSSJENDDKEW"
e = encode(s)
print(e, decode(e) == s)
Prints:
3AB6NDJ3SJEN2DKEW True
Your "and vice versa" sentence sounds like the program needs to detect itself whether to encode or to decode, so here's that (proof of correctness left as an exercise :-)
def switch(s):
e = re.sub(r'(\D)\1+', lambda m: str(len(m.group(0)))+m.group(1), s)
d = re.sub('(\d+)(.)', lambda m: int(m.group(1))*m.group(2), s)
return e if e != s else d
I am having a small problem in my code. I am trying to reverse the words and the character of a string. For example "the dog ran" would become "ehT god nar"
The code almost works. It just does not add spaces. How would you do that?
def reverseEachWord(str):
reverseWord=""
list=str.split()
for word in list:
word=word[::-1]
reverseWord=reverseWord+word+""
return reverseWord
You are on the right track. The main issue is that "" is an empty string, not a space (and even if you fix this, you probably don't want a space after the final word).
Here is how you can do this more concisely:
>>> s='The dog ran'
>>> ' '.join(w[::-1] for w in s.split())
'ehT god nar'
def reversed_words(sequence):
return ' '.join(word[::-1] for word in sequence.split())
>>> s = "The dog ran"
>>> reversed_words(s)
... 'ehT god nar'
name=input('Enter first and last name:')
for n in name.split():
print(n[::-1],end=' ')
You can also deal with noise in the string using the re module:
>>> import re
>>> s = "The \n\tdog \t\nran"
>>> " ".join(w[::-1] for w in re.split(r"\s+", s))
'ehT god nar'
Or if you don't care:
>>> s = "The dog ran"
>>> re.sub(r"\w+", lambda w: w.group(0)[len(w.group(0))::-1], s)
'Teh god nar'
def reverse_words(sentence):
return " ".join((lambda x : [i[::-1] for i in x])(sentence.split(" ")))
Another way to go about it is by adding a space to your words reverseWord=reverseWord+word+" " and removing the space at the end of your output by using .strip()
def reverse_words(str):
reverseWord = ""
list = str.split()
for word in list:
word = word[::-1]
reverseWord = reverseWord + word + " "
return reverseWord.strip()
check out this post on how it's used
Here is a solution without using join / split :
def reverse(sentence):
answer = ''
temp = ''
for char in sentence:
if char != ' ':
temp += char
continue
rev = ''
for i in range(len(temp)):
rev += temp[len(temp)-i-1]
answer += rev + ' '
temp = ''
return answer + temp
reverse("This is a string to try")