Python- How to fix failed testcase on a has repeat function? - python-3.x

I've built a function that checks for repeats of a specific number in a list named xs. V is the number to check for repeats of. It needs to return True if there are more than one occurrences of the number and if there are none, it needs to return False.
I'm failing one test case which is input xs=[1,2,1] v=1, this function needs to return True, but my code is making it False. Can you see where I went wrong?
Here is my current code:
def has_repeat(xs, v):
count=0
for num in range(len(xs)):
if num == v:
count+=1
if count>1:
return True
else:
return False

You're actually iterating over the range of the length of the list, not the items in the list.
The range function returns a list of numbers from 0 (by default) to the number you provide, in this case 3 (not inclusive). See Python documentation.
As an example if you try:
l = [1, 2, 3]
print(range(len(l)))
It will print out [0, 1, 2]
What you should do is instead of
for num in range(len(xs))
do
for num in xs:
You can try it out on PyFiddle here
As an added tasty bonus, you could change this to use the .count method on your list of items to check how many occurrences of that number are in the list, removing the need to iterate the list at all, like so:
count = xs.count(v)

Related

cant break out of Python While loop

I'm quite new to Python so sorry in advance, I'm trying to break out of a While loop if a random number is not within a List of numbers.
Despite testing the output of the functions and confirming that an integer is in the List and it is in fact an integer and other methods return both True and False the While Statement ignores the value. See demo code.
import random,time
list=[i for i in range(10)]
print(list)
print(list[6]*10) # this returns an integer
if list[6]==12/2:
print('this evaluates as a int')
this=99 # sentry to run the while loop **** but cant index by
if 10/2 in list:
print('this also evaluates as an integer')
print(type(list))
print(type(this))
while this not in list:
this = random.randrange(9)
print(this,this in list)
time.sleep(.200)
list[this] = '*'
>>>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
60
this evaluates as a int
this also evaluates as an integer
<class 'list'>
<class 'int'>
6 True
3 True
4 True
5 True
5 False
Its obvious there's a flaw in the While function where it is unable see True or False correctly, thank you to those who proposed suggestions but i come up with my own.
I created a sentry boolean to pass the value to the While function
sentry=True
while sentry:
this = random.randrange(9)
print(this,this in list)
if this not in list:
sentry=False
time.sleep(.200)
list[this] = '*'
The while loop condition should evaluate to False when you want to break out of the loop. In your case, since you want to exit when this is not in list, then set your condition to this in list.
Here is your code with the fixed condition, keep in mind that since the list is directly modified from inside the loop, the loop will terminate after one iteration.
import random, time
list=[i for i in range(10)]
print(list)
this = random.randrange(9)
while this in list:
this = random.randrange(9)
print(this, this in list)
time.sleep(.200)
list[this] = '*'
print(list)
If you did not want the loop to terminate after one iteration, you may want to consider relocating the expression list[this] = '*'. (Though this solution may also end after one iteration based on probability)
import random, time
list=[i for i in range(10)]
print(list)
this = random.randrange(9)
while this in list:
list[this] = '*' # moved here
print(list)
this = random.randrange(9)
print(this, this in list)
time.sleep(.200)
EDIT based on comment
Since the goal is to replace integers with *'s until no integers remain in the original list, here are some modifications.
The while loop exits when the number of elements replaced is equal to the number of items in the original array. The indices that have not been replaced yet are stored in the array called available.
import random, time
lst = [i for i in range(10)]
print(lst)
num_replaced = 0
# available = list.copy()
available = list(range(len(lst)))
while num_replaced < len(lst):
this = random.choice(available)
available.remove(this) # the index just chosen is no longer available
lst[this] = '*'
num_replaced += 1

How can I count all deleted elements when I remade the list into a set(Python)

I need to make a function, which will take a list or tuple and remade it into a set. As there are no duplicate elements in the set, I need to write the number of all deleted elements. This is my code,
def find_type(arg):
if isinstance(arg, list):
arg = set(arg)
return arg
elif isinstance(arg, tuple):
a = list(arg)
return set(a)
print(find_type((1, 2, 2, 3)))
and answer
{1, 2, 3}
The function works, so i just do not know how to count and write the number of deleted elements
You can use the following relation:
number1 = len(arg)
number2 = len(find_type(arg))
number = number1-number2
Number of deleted elements is simply the difference in length of list/tuple and set.
Also, you don't need to check if arg is instance of list or tuple (and even if you do, do it in one conditional). set accepts all iterable types (like lists, tuples, strings, etc.).

If condition working differently for same value in python

I am trying to write a function which will return True or False if the given number is not greater than 2.
So simple, but the if condition is returning different outputs for same value '2'. The code I used is:
The code I used is:
ele_list = [1,2,3,2]
for i in ele_list:
if not i>2:
print(i,False)
ele_list.remove(i)
print(ele_list)
The ouput I am receiving is:
1 False
[2, 3, 2]
2 False
[3, 2]
I am confused to see that the first 2 in the list is passing through the if condition but the second 2 in the list is not passing through the condition. Please help me figure out this..
Removing elements from the list you're looping over is generally a bad idea.
What's happening here is that when you're removing an element, you're changing the length of the array, and therefor changing what elements are located at what indexes as well as changing the "goal" of the forloop.
Lets have a look at the following example:
ele_list = [4,3,2,1]
for elem in ele_list:
print(elem)
ele_list.remove(elem)
In the first iteration of the loop elem is the value 4 which is located at index 0. Then you're removing from the array the first value equal to elem. In other words the value 4 at index 0 is now removed. This shifts which element is stored at what index. Before the removal ele_list[0] would be equal to 4, however after the removal ele_list[0] will equal 3, since 3 is the value that prior to the removal was stored at index 1.
Now when the loop continues to the second iteration the index that the loop "looks at" is incremented by 1. So the variable elem will now be the value of ele_list[1] which in the updated list (after the removal of the value 4 in the previous iteration) is equal to 2. Then you're (same as before) removing the value at index 1 from the list, so now the length of the list just 2 elements.
When the loops is about to start the third iteration it checks to see if the new index (in this case 2) is smaller than the length of the list. Which its not, since 2 is not smaller than 2. So the loop ends.
The simplest solutions is to create a new copy of the array and loop over the copy instead. This can easily be done using the slice syntax: ele_list[:]
ele_list = [1,2,3,2]
for elem in ele_list[:]:
if not elem > 2:
print(elem, False)
ele_list.remove(elem)
print(ele_list)
the problem is that you're modifying your list as you're iterating over it, as mentioned in #Olian04's answer.
it sounds like what you really want to do, however, is only keep values that are > 2. this is really easy using a list comprehension:
filtereds_vals = [v for v in ele_list if v > 2]
if you merely want a function that gives you True for numbers greater than 2 and False for others, you can do something like this:
def gt_2(lst):
return [v > 2 for v in lst]
or, finally, if you want to find out if any of the values is > 2 just do:
def any_gt_2(lst):
return any(v > 2 for v in lst)
I think the problem here is how the remove function interacts with the for function.
See the documentation, read the "note" part:
https://docs.python.org/3.7/reference/compound_stmts.html?highlight=while#grammar-token-for-stmt
This can lead to nasty bugs that can be avoided by making a temporary copy using a slice of the whole sequence
A possible solution, as suggested into the documentation:
ele_list = [1,2,3,2]
for i in ele_list[:]:
if not i>2:
print(i,False)
ele_list.remove(i)
print(ele_list)
"""
1 False
[2, 3, 2]
2 False
[3, 2]
2 False
[3]
"""

What is the empty dictionary used for in the code?

I'm doing practice problems in python on Leetcode (still learning). This is the problem:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
my code is
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
dict = {}
for counter, i in enumerate(nums):
a = target- i
if a in dict:
return (dict[a], counter)
dict[i] = counter
It runs fine and passes all the tests however I found a common reason this works is for the dict = {}
What is the reason for this dictionary and how does this code recognize cases for (3,3) target = 6 where there are duplicates and index matters. A basic run down of why the code works would be great!
The dictionary stores as keys the numbers in the list with their index as a value.
For example:
[2, 7, 11, 15] -> {'2':0, '7':1, '11':2, '15':3}
There is never a duplicate inserted, if the same number appears twice, the index will be replaced with the new index where it appears.
In the case of duplicate, it is important to test all value on the first list, and to store index on a separated dict in order to be sur that you will never test in dictionnary the actually tested value.
By using a dictionnary in order to find the index of the right number, you can't store duplicate.
Since in dictionnary you can't have 2 values with the same key, if duplicate, you just change the old index with the new one.
For example, if dict == {'3': 0, '2':1} and the tested value is 2, the dict == {'3': 0, '2':2}.
And if the target is reach by duplicate number (2+2 for target 4 for example), nothing is stored cause of the return in the if a in dict: return (dict[a], counter)

Function that removes zeroes from list?

I just need a function that removes zeroes from an input list
def no_zero(a):
pos=0
while (pos+1)<=len(a):
if a[pos] == "0":
a.remove[pos]
pos= pos +1
return a
print(no_zero([0,1,0,2,0,3]))
I should be getting an output of 1,2,3 but instead it skips right to return a. Any pointers as to why? Cheers.
You can use a list comprehension:
def no_zero(a):
return [x for x in a if x != 0]
print(no_zero([0,1,0,2,0,3]))
Additionally, the reason your code currently isn't working is because you are comparing the items to a string ("0") instead of an integer (0). You are also attempting to modify a list as you iterate over it, which means that your indices don't correspond to the original indices of the list, and your result will be wrong.

Resources