List Comprehension with "if" is not returning the same output as when I make a For Loop when counting the number of unique letters in a word - python-3.x

Can someone explain to me why there is a difference in output when using nested loops vs nested list comprehension?
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
def unique_english_letters (word) :
unique = []
for i in word:
if i not in unique:
unique.append(i)
return len(unique)
print(unique_english_letters("mississippi"))
# outputs 4 (my expected output)
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
def unique_english_letters (word) :
unique = []
unique = [i for i in word if i not in unique]
return len(unique)
print(unique_english_letters("mississippi"))
#outputs 11 (length of mississippi"
^ Output

In the second example, this:
unique = []
unique = [i for i in word if i not in unique]
is equivalent to:
unique = [i for i in word if i not in []]
unique is an empty list while the list comprehension is evaluated, and then unique is re-assigned the results.
To do what you want in simple terms, use a set which can only contain unique values, and use set intersection(& operator) to generate the set of letters contained in word:
letters = set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
def unique_english_letters(word):
return len(letters & set(word))
print(unique_english_letters("mississippi"))
# output: 4

Related

Suppose we have a list of 3-letter words with 3 elements, but each word is also a list. The function return the character at the given index

Suppose we have a list of 3-letter words with 3 elements, but each word is also a list. See example below:
word_list = [ ['r','e','d'] , ['p','e','a'] , ['z','i','p'] ]
Create a function named getCharacterAt that accepts 2 arguments - word_list and index_of_character. The function should be able to return the character at the given index. (If index_of_character is 3, we get 3rd letter in the whole list which is 'd'. If it is 5, we get 'e'. If 9, we get 'p'.
word_list = [ ['r','e','d'] , ['p','e','a'] , ['z','i','p'] ]
new_word_list = []
for i in word_list:
new_word_list = new_word_list + i
def getCharacterAt(word_list: list, index_of_character: int):
return word_list[index_of_character - 1]
print(getCharacterAt(new_word_list, 3))
# Output: d
In this case, I have created a 'new_word_list' with the union of each element of 'word_list'. Then, following your description, you just return the index - 1 element of the request (remember that first list index is 0)

Check list for part of value and return whole value

I have a master list of ID numbers and another list of partial ID numbers. I need to check if the partial ID number is in the master list. If so, I need to return the whole ID number into a new list. What I have:
master_list = ['20000-K-A', '20000-K-B', '20000-K-C', '30000-R-X', '30000-R-V', '30000-R-F']
partial_list = [20000, 40000, 500000]
new_list =[]
for x in partial_list:
if x in master_list:
new_list.append(x)
print(new_list)
Now this only works if the partial ID number is EXACTLY what is in the master list. How do I return the value from the master list so that I can add it to the new list?
One option is to create a lookup dictionary first from master_list (note that the master_list is a list of strings while partial_list is a list of integers, so we need to cast the prefix to int):
d = {}
for item in master_list:
k, _ = item.split('-', maxsplit=1)
d.setdefault(int(k), []).append(item)
which looks like:
{20000: ['20000-K-A', '20000-K-B', '20000-K-C'],
30000: ['30000-R-X', '30000-R-V', '30000-R-F']}
Then iterate over partial_list to get the partially matching Ids:
new_list =[]
for x in partial_list:
new_list.extend(d.get(x, []))
Output:
['20000-K-A', '20000-K-B', '20000-K-C']

Assign matched item in list to a variable

The motive is to check if any of items in a list are contained in another list, and in case there is a match, assign it to a variable in a 'pythonic' fashion
if any('a','b','c') in ['b','x','y','z']:
#now i want to assign the matched 'b' to a variable concisely.
#In case of multiple matches , any match/ first match may be assigned
I want to avoid this :
lst = ['b','x','y','z']
if 'a' in lst:
var = 'a'
elif 'b' in lst"
var = 'b'
# and so on
You can use a function that returns either the first matched element or None in case no matched elements are found:
li_1 = ['a','b','c']
li_2 = ['b','x','y','z']
def find(li_1, li_2):
for e in li_1:
if e in li_2:
return e
print(find(li_1, li_2))
# b
print(find(['a'], ['b']))
# None
Note that this is an O(n^2) solution. If the items are hashable you can get an O(1) solution using sets intersection (and as a bonus you will get all matched elements):
li_1 = ['a','b','c']
li_2 = ['b','x','y','z']
s1 = set(li_1)
s2 = set(li_2)
print(s1.intersection(s2)) # or print(s1 & s2)
# {'b'}

split a string in list

I have a list containing string values:
a_list = ['1/one','2/two','3/three']
I want to split the number from a word like this:
number = [1,2,3]
words = [one,two,three]
Then I make a condition if the number equal one or three then add the numbers to a new list. here is my code:
import re
new_list = []
for i in a_list:
word =re.findall(r"[\w']+",i)[1]
number = re.findall(r"[\w']+",i)[0]
if word == 'one' or word == 'three' :
new_list.append(number)
I got an error :
IndexError: list index out of range
any help?... Thanks in advance

Return a dictionary with keys that are the first letter of a word and lists of those words?

I want to write a function that takes a list of words and keys and outputs those keys as dictionary keys with any words starting with that letter attached.
How could this be achieved using simple python 3 code?
eg. takes (['apples', 'apple', 'bananna', 'fan'], 'fad')
returns {'a' : ['apple', 'apples'], 'f' : ['fan']}
so far i have tried:
def dictionary(words, char_keys)
char_keys = remove_duplicates(char_keys)
ret = {}
keys_in_dict = []
words = sorted(words)
for word in words:
if word[0] in char_keys and word[0] not in keys_in_dict:
ret[word[0]] = word
keys_in_dict.append(word[0])
elif word[0] in keys_in_dict:
ret[word[0]] += (word)
return ret
This gives kinda the right output but it the output is in a single string rather than a list of strings.(the def is not indented properly i know)
If the input is a list of strings, you can check if the char is in the dict, if yes, append the word, otherwise add a list with the word:
def dictionary(inpt):
result = {}
for word in inpt:
char = word[0]
if char in result:
result[char].append(word)
else:
result[char] = [word]
return result
The modern way to do this is to use a collections.defaultdict with list as argument.
def dictionary(inpt):
result = defaultdict(list)
for word in inpt:
result[word[0]].append(word)
return result
Not sure if your list of inputs are consisted with only strings or it can also include sub-lists of strings (and I'm not so sure why "fad" disappeared in your example). Obviously, in the latter scenario it will need some more effort. For simplicity I assume if contains only strings and here's a piece of code which hopefully points the direction:
d = {}
for elem in input_list[0]:
if elem[0] in input_list[1]
lst = d.get(elem[0], [])
lst.append(elem)
d[elem] = lst

Resources