Variable not reassigned when changed in for loop - python

The goal of this code is to count the word that appears the most within the given list. I planned to do this by looping through the dictionary. If a word appeared a greater number of times than the value stored in the variable rep_num, it was reassigned. Currently, the variable rep_num remains 0 and is not reassigned to the number of times a word appears in the list. I believe this has something to do with trying to reassign it within a for loop, but I am not sure how to fix the issue.
def rep_words(novel_list):
rep_num=0
for i in range(len(novel_list)):
if novel_list.count(i)>rep_num:
rep_num=novel_list.count(i)
return rep_num
novel_list =['this','is','the','story','in','which','the','hero','was','guilty']
In the given code, 2 should be returned, but 0 is returned instead.

In you for loop you are iterating over the numbers and not list elements themselves,
def rep_words(novel_list):
rep_num=0
for i in novel_list:
if novel_list.count(i)>rep_num:
rep_num=novel_list.count(i)
return rep_num

You're iterating over a numeric range, and counting the integer i, none of which values exist in the list at all. Try this instead, which returns the maximum frequency, and optionally a list of words which occur that many times.
novel_list =['this','is','the','story','in','which','the','hero','was','guilty']
def rep_words(novel_list, include_words=False):
counts = {word:novel_list.count(word) for word in set(novel_list)}
rep = max(counts.values())
word = [k for k,v in counts.items() if v == rep]
return (rep, word) if include_words else rep
>>> rep_words(novel_list)
2
>>> rep_words(novel_list, True)
(2, ['the'])
>>> rep_words('this list of words has many words in this list of words and in this list of words is this'.split(' '), True)
(4, ['words', 'this'])

You've an error in your function (you're counting the index, not the value), write like this:
def rep_words(novel_list):
rep_num=0
for i in novel_list:
if novel_list.count(i)>rep_num: #you want to count the value, not the index
rep_num=novel_list.count(i)
return rep_num
Or you may try this too:
def rep_words(novel_list):
rep_num=0
for i in range(len(novel_list)):
if novel_list.count(novel_list[i])>rep_num:
rep_num=novel_list.count(novel_list[i])
return rep_num

Related

Find the most occurring character in a string

This piece of code is going to find the most occurring chr in a string ,and it almost works fine through a dictionary ,but unfortunately the problem is that I want to make it return the last key when there are two keys with the same frequency ,but it returns the first one.
And this is what I have done so far:
def most_frequent_letter(s):
st = s.lower().replace(' ', '')
frequencies = {}
for items in st:
if items in frequencies:
frequencies[items] += 1
else:
frequencies[items] = 1
return max(frequencies, key=frequencies.get)
most_frequent_letter('mmmaaa')
Out[48]: 'm'
However I don't know how to return 'a' instead of 'm'.
Here's a way that creates a reverse frequency dictionary. I also made the creation of the frequency dictionary and its reverse fairly succinct by using a dictionary comprehension:
def most_frequent_letter(s):
st = s.lower().replace(' ', '')
frequencies = {}
frequencies = {item: frequencies.setdefault(item, 0) + 1 for item in st}
rev_freq = {count: key for key, count in frequencies.items()}
return rev_freq[max(rev_freq)]
print(most_frequent_letter('nnmmmaaa')) # -> a
Python max function always returns the first maximum occurrence.
Hence, if you always want the last key, then you can just reverse the original string in your code.
def most_frequent_letter(s):
st = s.lower().replace(' ', '')
st = st[::-1]
frequencies = {}
for items in st:
if items in frequencies:
frequencies[items] += 1
else:
frequencies[items] = 1
return max(frequencies, key=frequencies.get)
Or sort the string first if you want the lowest valued key.
You can also just create your own max function instead to suit your needs.
def most_frequent_letter(word):
letters = list(word)
return (max(set(letters), key = letters.count))
print(most_frequent_letter('mmmaaa'))
# output:m
print(most_frequent_letter('some apples are green'))
# output: e
max() will return the highest value in a list. The key argument takes a single argument function to customize the sort order, in this case, it’s letters.count. The function is applied to each item on the iterable.
letters.count is a built-in function of list. It takes an argument and will count the number of occurrences for that argument. So letters.count('m') will return 3 and letters.count(a) returns 3.
set(test) returns all the unique values from test, so {3, 3}
So what we do in this single line of code is take all the unique values of test, which is {1, 3}. Next, max will apply the list.count function to them and return the maximum value.
collections library has Counter which does the job for you: We normalize the word with lower casing and replace space before reverse string to have last appearance first.
from collections import Counter
word = 'mmmaaa'
characters = Counter(reversed(word.lower().replace(' ', '')))
# most common
print(characters.most_common(1))
yes you can get both m and a, it depends how you want to get the output but I have taken a string just for example
def most_frequent_letter(s):
st = s.lower().replace(' ', '')
frequencies = {}
for items in st:
if items in frequencies:
frequencies[items] += 1
else:
frequencies[items] = 1
max_val=max(frequencies.values())
result=""
for key,value in frequencies.items():
if value==max_val:
result+=key
return result
result=most_frequent_letter('mmmaaa')
print(result)
the output will be "ma"
In python when you use the max function it will return the first max frequency, if you want the second max frequency you could try to delete from the list the 'm's so after that the first max frequency will be 'a'.

for loop while decrementing the size of the list

so I have a list of 5 or fewer elements and the elements are just integers from 0-9 and the elements are randomly assigned and its possible for the list to have 5 zeros or 5 ones etc, and I have the following function to check if there is a zero in the list. this will return the index of the first zero it finds. just ignore the .getValue()
def check0(self):
'''
check for the index of the first card with value 0 in hand
:return:
'''
index = 0
found = False
while not found and index<len(self.hand):
if self.hand[index].getValue() == 0:
found = True
index += 1
if not found:
index = -1
return index
but the problem is that it always returns the first zero it finds in the list. in another class I am using this function to check if the hand has any zeros.
I need to write a for loop or some other loop that will traverse the list hand and tell me if all the elements in the hand are zeros.
so the only solution I can think of for this problem is to traverse the list once and when the first zero is found increment the counter and then traverse the list again this time excluding the zero that had already been found.
for example:
I have the list
[0,0,0,0,0]
in the first traversal, the check0() method will return the index 0 for the first zero but then I traverse the list again this time excluding the first zero and repeating that until I reach the last element.
I was thinking something like this:
def find_zeros():
counter = 0
for I in some_list(0,len(some_list),-1):
if I.check0() != -1:
counter += 1
if counter == len(some_list):
return True
return False
can anyone help me with this issue?
let me know if anything is unclear
also I'm not allowed to import anything and time complexity isn't an issue
"I need to write a for loop or some other loop that will traverse the list hand and tell me if all the elements in the hand are zeros." (OP)
Well, to check if all elements in your list are zero you could use count:
lst1 = [0,0,0,0,0]
print(len(lst1) == lst1.count(0))
Or maybe list comprehension:
lst1 = [0,0,0,0,0]
print(lst1 == [nr for nr in lst1 if nr == 0])
probably better written using all like:
lst1 = [0,0,0,0,0]
print(all(i==0 for i in lst1))
Or maybe create a second list the same size:
lst1 = [0,0,0,0,0]
print(lst1 == [0]*len(lst1))
You can use enumerate for this type of problem.
for index, ch in enumerate(list_name):
print(i, ch)
This will give you the index of each and every character in the list.
You can use an 'if' statement later to check if 'ch' is a zero.
Hope it helped.
listt=[1,0,2,0,1]
for i in range(len(listt)):
if listt[i]==0:
print(i)
break #if you want to find first occurence
To check all ekements are 0,
if len(set(listt))==1 and listt[0]==0:
print("All index have 0 ")
You could define the function like this:
def check0(self):
index = (self.hand+[0]).index(0)
return -1 if not any(self.hand) else index

Problem with coding a function that returns the maximum integer from even positions of a string

Make a function that receives a string containing only digits and may also be an empty string, which returns an integer value which is the maximum of all the digits that are in the EVEN POSITIONS of the original string.
If the empty string, the function should return -1.
For example:
max_even_pos("123454321") returns 5, because 5 is the maximum of 1,3,5,3,1, which are the digits in the original string in even positions.
# My code
def max_even_pos(st):
if not st:
return -1 ### This line satisfies the empty list condition
for i in range(len(st)): ### Problem I have. Trying to find
## the max integer from even positions
num_list = [i] # assigns elements to the list
if i%2 == 0: # checks if elements are even
return max(num_list) # result
My only problem is trying to get the code to find the greatest integer in the even position of the original string. I think "num_list = [i]" causes the error, but I am unsure how to change this so it executes properly.
As of right now, it outputs 0 for all cases
Your current code ensures that num_list has no more than a single element. When you hit the first even index, 0, you stop and return that index, without regard to the input value. You have several errors to correct:
Put the return after the loop. You have to get through all of the input before you can return the required value.
Accumulate the values with append. Your current code keeps only the last one.
Accumulate the input values; i is the position, not the value. I believe that you want st[i]
Also look into better ways to iterate through a list. Look at for loops or list slicing with a step of 2. If you are ready for another level of learning, look up list comprehension; you can reduce this function to a one-line return.
#Prune is correct. Maybe comparing the lines below to your original will help you for next time....
test_string = "123454321"
def max_even_pos(st):
num_list = []
if not st:
return -1
for i in range(len(st)):
if i%2 == 0:
num_list.append(st[i])
return max(num_list)
print(max_even_pos(test_string))

Populating a List - Python assigns index and gives error

I have a solution to count the number of occurrences of each letter in a string and return a dict.
def count_characters(in_str):
all_freq = {}
for i in in_str:
if i in all_freq:
all_freq[i] += 1
else:
all_freq[i] = 1
return all_freq
count_characters("Hello")
It works.
I am trying to understand how Python automatically assigns each letter as the key to the dict - its not explicitly assigned. I replace the null dictionary assignment with a list and expect to get just the frequency, without the letter.
def count_characters(in_str):
all_freq = []
for i in in_str:
if i in all_freq:
all_freq[i] += 1
else:
all_freq[i] = 1
return all_freq
count_characters("Hello")
I get an error.
TypeError: list indices must be integers or slices, not str
My question is:
How does each letter get automatically assigned as the key?
How can I return just the numbers as a list - without the letter?
How does each letter get automatically assigned as the key?
You are doing it explicitly in all_freq[i] = 1. Here, i contains a letter (though I think the variable could be named better — i typically stands for an idex of some sort, which this isn't).
How can I return just the numbers as a list - without the letter?
You could still build a dictionary and then return list(all_freq.values()). Though, if you do that, how would you know which letter each count corresponds to?
This is probably not relevant for your exercise, but the standard library already has a class for doing this sort of counting: collections.Counter.
List are indexing with integer, in your second exemple you use dictionary synthax with a list, that why python complain.
You can use count method
def count_characters(in_str):
all_freq = []
for i in in_str:
all_freq.append(in_str.count(i))
return all_freq
count_characters("Hello")
Edit : I agree with #NPE comment
You could still build a dictionary and then return list(all_freq.values()). Though, if you do that, how would you know which letter each count corresponds to?
This is probably not relevant for your exercise, but the standard library already has a class for doing this sort of counting: collections.Counter.
It's simple when we use built-in methods of dictionary like .keys(), .values()
Example:
def count_char(string):
dict = {}
count = 0
for i in string :
if i in dict.keys():
dict[i] +=1
else:
dict[i] = 1
for j in dict.values():
count += j
print(dict)
print(count)

Python string function that removes one duplicate pair from multiple duplicates

I'm looking for a string function that removes one duplicate pair from multiple duplicates.
What i'd like the function to do:
input = ['a','a','a','b','b','c','d','d','d','d']
output = ['a','c']
heres what I have so far:
def double(lijst):
"""
returns all duplicates in the list as a set
"""
res = set()
zien = set()
for x in lijst:
if x in zien or zien.add(x):
res.add(x)
return(res)
def main():
list_1 = ['a','a','a','b','b','c']
list_2 = set(list_1)
print(list_2 - double(list_1))
main()
The problem being that it removes all duplicates, and doesn't leave the 'a'. Any ideas how to approach this problem?
For those interested why I need this; I want to track when a levehnstein function is processing vowel steps, if a vowel is being inserted or deleted I want to assign a different value to 'that step' (first I need to tract if a vowel has passed on either side of the matrix before the current step though) hence I need to remove duplicate pairs from a vowel list (as explained in the input output example).
These solves your problem. Take a look.
lsit = ['a','a','a','b','b','c']
for i in lsit:
temp = lsit.count(i)
if temp%2==0:
for x in range(temp):
lsit.remove(i)
else:
for x in range(temp-1):
lsit.remove(i)
print lsit
Output:
['a','c']
Just iterate through the list. If an element does not exist in the result, add it to the set. Or if there does already have one in the set, cancel out those two element.
The code is simple:
def double(l):
"""
returns all duplicates in the list as a set
"""
res = set()
for x in l:
if x in res:
res.remove(x)
else:
res.add(x)
return res
input = ['a','a','a','b','b','c','d','d','d','d']
print double(input)

Categories

Resources