The function will return a list containing all the letters found in both strings. All the letters returned should be lowercase.
There should be no duplicate letters in the list returned by your function.
Example:
string_scramble('GraSS', 'grilled cheese') should return: ['g','r','s']
def string_scramble(string_one, string_two):
string_one = "hello there"
string_two = "welcome to town"
a = list(set(string_one) & set(string_two))
for i in a:
print(i)
a = set(string_one).union(string_two)
You could use a lambda expression that solves your question:
scrambler = lambda str1, str2: list(set(str1.lower())&set(str2.lower()))
Just try
scrambler('GraSS','grilled cheese')
def string_scramble(string_one, string_two):
new_list = []
for letter in sorted(set(string_one.lower())):
if letter in sorted(set(string_two.lower())):
new_list.append(letter)
return new_list
print(string_scramble('grass', 'grilled cheese'))
output:
['g', 'r', 's']
I added .lower() because it appears as if you want to ignore the case based on your question. In Python, we can simply convert the entire string to lower case. The set function will return the output that you are looking for.
Also of interest, I used sorted here so that you can keep the strings in order in the set, because a set is generally unordered.
string_one = "hello there"
string_two = "welcome to town"
set(string_one.lower()) & set(string_two.lower())
->>> {'t', 'l', 'e', ' ', 'o'}
Related
What is the easiest way in Python to replace a character in a string?
For example:
text = "abcdefg";
text[1] = "Z";
^
Don't modify strings.
Work with them as lists; turn them into strings only when needed.
>>> 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'
Python strings are immutable (i.e. they can't be modified). There are a lot of reasons for this. Use lists until you have no choice, only then turn them into strings.
Fastest method?
There are three ways. For the speed seekers I recommend 'Method 2'
Method 1
Given by this answer
text = 'abcdefg'
new = list(text)
new[6] = 'W'
''.join(new)
Which is pretty slow compared to 'Method 2'
timeit.timeit("text = 'abcdefg'; s = list(text); s[6] = 'W'; ''.join(s)", number=1000000)
1.0411581993103027
Method 2 (FAST METHOD)
Given by this answer
text = 'abcdefg'
text = text[:1] + 'Z' + text[2:]
Which is much faster:
timeit.timeit("text = 'abcdefg'; text = text[:1] + 'Z' + text[2:]", number=1000000)
0.34651994705200195
Method 3:
Byte array:
timeit.timeit("text = 'abcdefg'; s = bytearray(text); s[1] = 'Z'; str(s)", number=1000000)
1.0387420654296875
new = text[:1] + 'Z' + text[2:]
Python strings are immutable, you change them by making a copy.
The easiest way to do what you want is probably:
text = "Z" + text[1:]
The text[1:] returns the string in text from position 1 to the end, positions count from 0 so '1' is the second character.
edit:
You can use the same string slicing technique for any part of the string
text = text[:1] + "Z" + text[2:]
Or if the letter only appears once you can use the search and replace technique suggested
below
Starting with python 2.6 and python 3 you can use bytearrays which are mutable (can be changed element-wise unlike strings):
s = "abcdefg"
b_s = bytearray(s)
b_s[1] = "Z"
s = str(b_s)
print s
aZcdefg
edit: Changed str to s
edit2: As Two-Bit Alchemist mentioned in the comments, this code does not work with unicode.
Strings are immutable in Python, which means you cannot change the existing string.
But if you want to change any character in it, you could create a new string out it as follows,
def replace(s, position, character):
return s[:position] + character + s[position+1:]
replace('King', 1, 'o')
// result: Kong
Note: If you give the position value greater than the length of the string, it will append the character at the end.
replace('Dog', 10, 's')
// result: Dogs
This code is not mine. I couldn't recall the site form where, I took it. Interestingly, you can use this to replace one character or more with one or more charectors.
Though this reply is very late, novices like me (anytime) might find it useful.
Change Text function.
mytext = 'Hello Zorld'
# change all Z(s) to "W"
while "Z" in mytext:
# replace "Z" to "W"
mytext = mytext.replace('Z', 'W')
print(mytext)
Like other people have said, generally Python strings are supposed to be immutable.
However, if you are using CPython, the implementation at python.org, it is possible to use ctypes to modify the string structure in memory.
Here is an example where I use the technique to clear a string.
Mark data as sensitive in python
I mention this for the sake of completeness, and this should be your last resort as it is hackish.
I like f-strings:
text = f'{text[:1]}Z{text[2:]}'
In my machine this method is 10% faster than the "fast method" of using + to concatenate strings:
>>> timeit.timeit("text = 'abcdefg'; text = text[:1] + 'Z' + text[2:]", number=1000000)
1.1691178000000093
>>> timeit.timeit("text = 'abcdefg'; text = f'{text[:1]}Z{text[2:]}'", number =1000000)
0.9047831999999971
>>>
Actually, with strings, you can do something like this:
oldStr = 'Hello World!'
newStr = ''
for i in oldStr:
if 'a' < i < 'z':
newStr += chr(ord(i)-32)
else:
newStr += i
print(newStr)
'HELLO WORLD!'
Basically, I'm "adding"+"strings" together into a new string :).
To replace a character in a string
You can use either of the method:
Method 1
In general,
string = f'{string[:index]}{replacing_character}{string[index+1:]}'
Here
text = f'{text[:1]}Z{text[2:]}'
Method 2
In general,
string = string[:index] + replacing_character + string[index+1:]
Here,
text = text[:1] + 'Z' + text[2:]
if your world is 100% ascii/utf-8(a lot of use cases fit in that box):
b = bytearray(s, 'utf-8')
# process - e.g., lowercasing:
# b[0] = b[i+1] - 32
s = str(b, 'utf-8')
python 3.7.3
I would like to add another way of changing a character in a string.
>>> text = '~~~~~~~~~~~'
>>> text = text[:1] + (text[1:].replace(text[0], '+', 1))
'~+~~~~~~~~~'
How faster it is when compared to turning the string into list and replacing the ith value then joining again?.
List approach
>>> timeit.timeit("text = '~~~~~~~~~~~'; s = list(text); s[1] = '+'; ''.join(s)", number=1000000)
0.8268570480013295
My solution
>>> timeit.timeit("text = '~~~~~~~~~~~'; text=text[:1] + (text[1:].replace(text[0], '+', 1))", number=1000000)
0.588400217000526
A solution combining find and replace methods in a single line if statement could be:
```python
my_var = "stackoverflaw"
my_new_var = my_var.replace('a', 'o', 1) if my_var.find('s') != -1 else my_var
print(f"my_var = {my_var}") # my_var = stackoverflaw
print(f"my_new_var = {my_new_var}") # my_new_var = stackoverflow
```
try this :
old_string = "mba"
string_list = list(old_string)
string_list[2] = "e"
//Replace 3rd element
new_string = "".join(string_list)
print(new_string)
I'm looking for a way to create a function that dynamically replaces all the initial or beginning letters of words in a sentence. I created a function that replaces the initial letters no problem.
def replace_all_initial_letters(original, new, sentence):
new_string = re.sub(r'\b'+original, new, sentence)
return new_string
test_sentence = 'This was something that had to happen again'
print(replace_all_initial_letters('h', 'b', test_sentence))
Output: 'This was something that bad to bappen again'
I would however like to be able to enter multiple options into this function using a dictionary or Hash Map. For example like using the following:
initialLetterConversion = {
'r': 'v',
'h': 'b'
}
Or I think there might be a way to do this using regex grouping perhaps.
I'm also having trouble implementing this for ending letters. I tried the following function but it does not work
def replace_all_final_letters(original, new, sentence):
new_string = re.sub(original+r'/s', new, sentence)
return new_string
print(replace_all_final_letters('n', 'm', test_sentence))
Expected Output: 'This was something that had to happem agaim'
Any help would be greatly appreciated.
By "simple" grouping you can access to the match with the lastindex attribute. Notice that such indexes starts from 1. re.sub accept as second argument a callback to add more flexibility for custom substitutions. Here an example of usage:
import re
mapper = [
{'regex': r'\b(w)', 'replace_with': 'W'},
{'regex': r'\b(h)', 'replace_with': 'H'}]
regex = '|'.join(d['regex'] for d in mapper)
def replacer(match):
return mapper[match.lastindex - 1]['replace_with'] # mapper is globally defined
text = 'This was something that had to happen again'
out = re.sub(regex, replacer, text)
print(out)
#This Was something that Had to Happen again
Ignore this if, for some reason, re is required for this. This is plain Python with no need for any imports.
The conversion map is a list of 2-tuples. Each tuple has a from and to value. The from and to values are not limited to a string of length 1.
This single function handles both the beginning and end of words although the mapping is for both 'ends' of the word and may therefore need some adaptation.
sentence = 'This was something that had to happen again'
def func(sentence, conv_map):
words = sentence.split()
for i, word in enumerate(words):
for f, t in conv_map:
if word.startswith(f):
words[i] = t + word[len(f):]
word = words[i]
if word.endswith(f):
words[i] = word[:-len(f)] + t
return ' '.join(words)
print(func(sentence, [('h', 'b'), ('a', 'x'), ('s', 'y')]))
Output:
Thiy way yomething that bad to bappen xgain
I am working on a list filter. This is as far as I've gone. I would like to remove every string that doesn't contain H, L OR C. So far this is my attemp
input_list = input("Enter The Results(leave a space after each one):").split(' ')
for i in input_list:
if 'H'not in i or 'L' not in i or 'C' not in i:
Use this pythonic code
input_list = input("Enter The Results(leave a space after each one):").split(' ') # this is the input source
after_removed = [a for a in input_list if ('H' not in a and 'L' not in a and 'C' not in a)] # this is the after removed 'H', 'L', and 'C' from the input_list
Using list comprehension, you can make python easier and faster
If you don't believe, just try it for yourself :D
For clarity, you can use a function
def contains_invalid_character(my_string):
return 'H' in my_string or 'L' in my_string or 'C' in my_string
# To be more pythonic, you can use the following
# return next((True for letter in ("H", "L", "C") if letter in my_string), False)
results = []
for i in input_list:
if not contains_invalid_character(i):
results.append(i)
# Or to be more pythonic
# results = [i for i in input_list if not contains_invalid_character(i)]
Question: DO NOT USE SETS IN YOUR FUNCTION: Uses lists to return a list of the common letters in the first and last names (the intersection) Prompt user for first and last name and call the function with the first and last names as arguments and print the returned list.
I can't figure out why my program is just printing "No matches" even if there are letter matches. Anything helps! Thanks a bunch!
Code so far:
import string
def getCommonLetters(text1, text2):
""" Take two strings and return a list of letters common to
both strings."""
text1List = text1.split()
text2List = text2.split()
for i in range(0, len(text1List)):
text1List[i] = getCleanText(text1List[i])
for i in range(0, len(text2List)):
text2List[i] = getCleanText(text2List[i])
outList = []
for letter in text1List:
if letter in text2List and letter not in outList:
outList.append(letter)
return outList
def getCleanText(text):
"""Return letter in lower case stripped of whitespace and
punctuation characters"""
text = text.lower()
badCharacters = string.whitespace + string.punctuation
for character in badCharacters:
text = text.replace(character, "")
return text
userText1 = raw_input("Enter your first name: ")
userText2 = raw_input("Enter your last name: ")
result = getCommonLetters(userText1, userText2)
numMatches = len(result)
if numMatches == 0:
print "No matches."
else:
print "Number of matches:", numMatches
for letter in result:
print letter
Try this:
def CommonLetters(s1, s2):
l1=list(''.join(s1.split()))
l2=list(''.join(s2.split()))
return [x for x in l1 if x in l2]
print CommonLetters('Tom','Dom de Tommaso')
Output:
>>> ['T', 'o', 'm']
for letter in text1List:
Here's your problem. text1List is a list, not a string. You iterate on a list of strings (['Bobby', 'Tables'] for instance) and you check if 'Bobby' is in the list text2List.
You want to iterate on every character of your string text1 and check if it is present in the string text2.
There's a few non-pythonic idioms in your code, but you'll learn that in time.
Follow-up: What happens if I type my first name in lowercase and my last name in uppercase? Will your code find any match?
Prior to set() being the common idiom for duplicate removal in Python 2.5, you could use the conversion of a list to a dictionary to remove duplicates.
Here is an example:
def CommonLetters(s1, s2):
d={}
for l in s1:
if l in s2 and l.isalpha():
d[l]=d.get(l,0)+1
return d
print CommonLetters('matteo', 'dom de tommaso')
This prints the count of the common letters like so:
{'a': 1, 'e': 1, 'm': 1, 't': 2, 'o': 1}
If you want to have a list of those common letters, just use the keys() method of the dictionary:
print CommonLetters('matteo', 'dom de tommaso').keys()
Which prints just the keys:
['a', 'e', 'm', 't', 'o']
If you want upper and lower case letters to match, add the logic to this line:
if l in s2 and l.isalpha():
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do you remove duplicates from a list whilst preserving order?
So the idea is the program takes a string of characters and removes the same
string with any duplicated character only appearing
once -- removing any duplicated copy of a character.
So Iowa stays Iowa but the word eventually would become eventually
Here is an inefficient method:
x = 'eventually'
newx = ''.join([c for i,c in enumerate(x) if c not in x[:i]])
I don't think that there is an efficient way to do it in a list comprehension.
Here it is as an O(n) (average case) generator expression. The others are all roughly O(n2).
chars = set()
string = "aaaaa"
newstring = ''.join(chars.add(char) or char for char in string if char not in chars)
It works because set.add returns None, so the or will always cause the character to be yielded from the generator expression when the character isn't already in the set.
Edit: Also see refaim's solutions. My solution is like his second one, but it uses the set in the opposite way.
My take on his OrderedDict solution:
''.join(OrderedDict((char, None) for char in word))
Without list comprehensions:
from collections import OrderedDict
word = 'eventually'
print ''.join(OrderedDict(zip(word, range(len(word)))).keys())
With list comprehensions (quick and dirty solution):
word = 'eventually'
uniq = set(word)
print ''.join(c for c in word if c in uniq and not uniq.discard(c))
>>> s='eventually'
>>> "".join([c for i,c in enumerate(s) if i==s.find(c)])
'evntualy'
note that using a list comprehension with join() is silly when you can just use a generator expression. You should tell your teacher to update their question
You could make a set from the string, then join it together again. This works since sets can only contain unique values. The order wont be the same though:
In [1]: myString = "mississippi"
In [2]: set(myString))
Out[2]: set(['i', 'm', 'p', 's'])
In [3]: print "".join(set(myString))
Out[3]: ipsm
In [4]: set("iowa")
Out[4]: set(['a', 'i', 'o', 'w'])
In [5]: set("eventually")
Out[5]: set(['a', 'e', 'l', 'n', 't', 'u', 'v', 'y'])
Edit: Just saw the "List Comprehension" in the title so this probably isnt what your looking for.
Create a set from the original string, and then sort by position of character in original string:
>>> s='eventually'
>>> ''.join(sorted(set(s), key=s.index))
'evntualy'
Taken from this question, I think this is the fastest way:
>>> def remove_dupes(str):
... chars = set()
... chars_add = chars.add
... return ''.join(c for c in str if c not in chars and not chars_add(c))
...
>>> remove_dupes('hello')
'helo'
>>> remove_dupes('testing')
'tesing'
word = "eventually"
evntualy = ''.join(
c
for d in [dict(zip(word, word))]
for c in word
if d.pop(c, None) is not None)
Riffing off of agf's (clever) solution but without making a set outside of the generator expression:
evntualy = ''.join(s.add(c) or c for s in [set()] for c in word if c not in s)