Python - loop inside ternary operator - python

I am learning python, and trying to use some ternary operators.
I am trying to make the function below using a ternary:
def array_count9(nums):
count = 0
for i in nums:
if i == 9:
count += 1
return count
I have tried:
def array_count9(nums):
count = 0
count += 1 if i == 9 for i in nums else pass
return count
which threw a SyntaxError, then after looking around I found this and changed my code for what I believed was better ordering:
def array_count9(nums):
count = 0
count += 1 if i == 9 else pass for i in nums
return count
Still receiving SyntaxError which is pointing at the for. I've tried using parentheses in different places too.
I have looked around and there are other related threads such as this and this, which resulted in me trying this:
def array_count9(nums):
count = 0
count += 1 if i == 9 else count == count for i in nums
return count
I've also tried other resources by searching Google, but I can't quite work it out. Please teach me.
Thanks

I think this is the most idiomatic way to write the code:
def array_count9(nums):
return sum(num == 9 for num in nums)
But you could also do this if you want to use the if/else construct:
def array_count9(nums):
return sum(1 if num == 9 else 0 for num in nums)

The blueprint for a ternary operator is:
condition_is_true if condition else condition_is_false
The statement where the syntax error occurs is at
count += 1 if i == 9 else pass for i in nums
ie count += 1 does not meet the blueprint specification, because condition_is_true should not need to be evaluated.

Okay so using your examples was a little tricky because a ternary operator can't include anything outside it's specific blueprint; that being the for loop you're trying to pass with it.
count += 1 if i == 9 for i in nums else pass
So after fiddling around with the code:
def array_count9(nums):
count = 0
count += 1 if i == 9 for i in nums else pass
return count
I was sure you were looking for something that works involving ternary operators and that for loop. So keeping your goal in mind, this is what I came up with.
numss = [3,6,9,10,35]
def count9(nums):
count = 0
a = count + 1
for i in nums:
count = (a if i == 9 else count) #This being the ternary operator
return count
print (count9(numss))
Hope this helps.

Related

How to check elements in a list WITHOUT using for loops?

Apologies if the title of the question is phrased badly. I am currently trying to make a function that takes in a list of integers from 1 to n, where n is the length of the list. The function should return the first value that is repeated in the list. Duplicates are NOT always next to one another. If one or more integers is less than 1 or if it is not a list, the function should return -1. If there are no duplicates, return 0.
This is my current code:
def find_duplicates(ls):
if type(ls) != list:
return -1
non_dupe = []
i = 0
while i < len(ls):
if ls[i] < 1:
return -1
break
if ls.count(i) > 1:
return i
break
else:
non_dupe.append(i)
i += 1
if len(non_dupe) == len(ls):
return 0
While this code works for a majority of test cases, it doesn't seem to pass
print(find_duplicates([1, 2, 2, 0]))
as it returns 2 instead of the expected -1. I am relatively new to Python and I can't seem to be able to fix this error. I've tried searching for ways to counter this problem but I am not allowed to use for loops to check through a list. Any help is greatly appreciated.
EDIT: I am not allowed to use any of the following but anything else is accepted.
for loops
min() / max()
enumerate() / zip ()
sort()
negative indexing e.g ls[-1]
list slicing
Your code returns a duplicate prematurely; traversing the list, the function first finds 2 as a duplicate, return it, and halts the function immediately. But it has not seen the 0 at the end.
So, you need to let the function see the list all the way towards the end, looking for a negative number. If a negative number is found along the way, you can halt the function. If it does not see a negative number until the end, then let it return the duplicate value:
def find_duplicates(ls):
if not isinstance(ls, list): # check whether ls is a list
return -1
dup = 0
seen = [] # list of numbers seen so far
i = 0 # index
while i < len(ls):
if ls[i] < 1: # if a negative number is found, return -1
return -1
if ls[i] in seen and dup == 0:
dup = ls[i]
seen.append(ls[i])
i += 1
return dup
print(find_duplicates([1, 2, 2, 0])) # -1
print(find_duplicates([1, 1, 2, 2, 3])) # 1
Problem is beacause you are breaking while loop when find a duplicated. In that case, function is finding first the duplicated.
Try this:
def find_duplicates(ls):
if type(ls) is not list:
return -1
duplicated = 0
i = 0
while i < len(ls):
if ls[i] < 1:
return -1
if ls.count(ls[i]) > 1 and duplicated == 0
duplicated = ls[i]
i += 1
return duplicated
Your test case returns 2 because 2 stay at lower indexes comparing to 0.
I would suggest to sort the list before moving on:
def find_duplicates(ls):
if type(ls) != list:
return -1
sorted_list = ls.sorted() #Assign sorted `ls` to another variable, while keeping the order of `ls` intact
non_dupe = []
i = 0
while i < len(ls):
if ls[i] < 1:
return -1
break
if ls.count(i) > 1:
return i
break
else:
non_dupe.append(i)
i += 1
if len(non_dupe) == len(ls):
return 0
Another method I would recommend is using set - a built-in data type of Python. Maybe you should consider trying this approach later on when all test cases are passed. Have a look at this Tutorial for set usage: https://www.w3schools.com/python/python_sets.asp.
You were very close. Try this:
def find_duplicates(ls):
if type(ls) != list:
return -1
non_dupe = []
i = 0
while i < len(ls):
if ls[i] < 1:
return -1
elif ls[i] in non_dupe:
return ls[i]
else:
non_dupe.append(i)
i += 1
return 0
my_list = [1,2,2,0]
result = list(set(filter(lambda x: my_list.count(x) > 1 , my_list)))
# Result => [2]
I hope this solves your problem

Why is my function returning a wrong value?

I just started learning Python recently. I cannot figure out the reason why my function is returning the wrong value. Basically, I want to calculate the total number of even numbers in a list.
Codes in myModule.py
def evenNum(x):
e_count = 0
for num in x:
if num % 2 == 0:
e_count += 1
return e_count
Codes in main.py
import sys
import myModule
inputList = [int(s) for s in sys.argv[1].split(',')]
print("no. of even numbers is:%d"%(myModule.evenNum(inputList)))
Output in cmd
C:\Users\belle\Testing\Exercise1> main.py 14,12,9,21,23,2
no. of even numbers is:1
The result should be 3 instead of 1...
Indentation. The previous version would just return 1 once it found an even value and None if x didn't have any.
def evenNum(x):
e_count = 0
for num in x:
if num % 2 == 0:
e_count += 1
return e_count

How to fix recursion function [duplicate]

This question already has an answer here:
Why Python recursive function returns None [duplicate]
(1 answer)
Closed 3 years ago.
I am trying to write a recursive function which takes an integer as its parameter and returns the number of pairs of numbers within the integer that sum to 10. For example, findPairs(28164730) would return 3 because 2+8=10, 6+4=10, and 7+3=10.
This is what my code looks like now:
def find(x):
x = str(x)
count = 0
if str((10 - int(x[0]))) in x:
count = count + 1
x = x[1:]
find(x)
elif len(x) > 1:
x = x[1:]
find(x)
return count
The problem I am having is that the function will always return that the count is 1 because I am calling it again for recursion and it is setting the count back to 0 instead of just adding 1 to the count every time a pair is found. Does anyone know how I can fix this?
Right now, your code isn't using the returned value of the recursive find call; it's just calling find(x). This will fix your problem:
def find(x):
x = str(x)
count = 0
if str((10 - int(x[0]))) in x:
# count = count + 1
x = x[1:]
count = 1 + find(x)
elif len(x) > 1:
x = x[1:]
count = find(x)
return count
One possible solution would be to simplify by e.g. not using recursion at all. See e.g. the following attempt:
def find(x):
x = str(x)
count = 0
for i in range(len(x)-1):
if str((10-int(x[i]))) in x[i+1:]:
count += 1
return count
Either have a separate function that declares count then calls find(), or set count as a global variable. I think the first method is preferable.
def get_count(x):
count = 0
find(str(x))
return count
Or something like that. Also if you use that method, make sure to remove the count = 0 from the original find function

Iteration that concatenates different strings based on conditions given

Currently having difficulty figuring out this one. I know that I am very near but I cannot figure out where I am going wrong.
I would like the output to show a string, where an even number corresponds to '?--' and an odd number corresponds to '?-', and concatenate all of the strings together. Eg. star_wars_iteration(3) should return '?-?--?-'
However, mine does not add up, it only returns it once.
def star_wars_iteration(num_enemy_ships):
counter = 1
result = ''
while counter in range(1,num_enemy_ships + 1):
if counter % 2 == 0:
return '?--'
elif counter % 2 == 1:
return '?-'
result = result + counter
counter = counter + 1
return stops the function as soon as it is reached. Also you confuse while and for. What you want is:
def star_wars_iteration(num_enemy_ships):
result = ''
for counter in range(1,num_enemy_ships + 1):
if counter % 2 == 0:
result += '?--'
elif counter % 2 == 1:
result += '?-'
return result
Or if you want to use while then use while counter <= num_enemy_ships : (using in range(...) works too but is unnecessarily inefficient) and make sure the counter = counter + 1 line is inside the while block.
Note: more concise and pythonic:
def star_wars_iteration(num_enemy_ships):
return ''.join('?-' if counter % 2 else '?--' for counter in range(1,num_enemy_ships + 1))
Why don't you use the Pythonic iterators and range function for what they are meant to be you don’t need to increment starting and end values in the range:
def star_wars_iteration(num_enemy_ships):
return "".join('?-' if index % 2 else '?--' for index in range(num_enemy_ships))

Understanding iterative properties of Python "in" operator within for loop and if statement

The following code returns the summation of the values in list "A" that exist before the first even value in the list.
Example:
if list A = [1,3,5,4] the result would return 1 + 3 + 5 = 9
if list A = [1,2,5,4] the result would return 1
def for_version(L):
found_even = False
total = 0
for num in L:
if num % 2 != 0 and not found_even:
total = total + num
else:
found_even = True
return total
A = [1,3,5,9]
for_version(A)
I don't understand how, after the first iteration, we don't lose the 1st integer in the list. In other words, here's how I imagine the code is working.
Starts at the first value in the list "A" and prepares to move through all values one at a time:
for num in L:
Checks the first iteration of the if statement:
if num % 2 != 0 and not found_even:
Although the first number in the list IS ODD, because found_even was set to False originally the code should move to the else statement:
else:
found_even = True
I imagine that the if statement has now been completed on the first value of the list and all that occurred was that the found_even bool was changed to True.
I assumed that the code would then move on; that the if statements would then be tested on the NEXT value in the list. This, however appears incorrect. If my thinking were right, in the example above, it would mean that the first value in the list "1" would be ignored when completing the summation, and we would end up with 3 + 5 = 8 NOT 1 + 3 + 5 = 9.
I obviously don't understand something very foundational about how the
for num in L:
line works... It's as if it did not, in fact, move to the next integer in the list and reruns the code on the first integer in the list. Can someone please explain why this is.
Although the first number in the list IS ODD, because found_even was set to False originally the code should move to the else statement[.]
You got your logic wrong right there. not False is true, so the if statement test tests true and the else suite is not executed.
You can test this yourself:
>>> num = 1 # odd
>>> found_even = False
>>> num % 2
1
>>> num % 2 != 0
True
>>> not found_even
True
>>> num % 2 != 0 and not found_even
True
The code itself is overly complicated; just return early. There is no need to iterate on, or use a flag; return ends a function and iteration:
def for_version(L):
total = 0
for num in L:
if num % 2 == 0:
return total
total += num
Alternatively, use break to stop the loop, and return afterwards.
The Python standard library has a helpful tool in the itertools library for this, called itertools.takewhile(); it'll give you all elements of an iterable until the given test fails. It then just stops iterating:
from itertools import takewhile
sum(takewhile(lambda x: x % 2, A))
I removed the != 0 test there; % 2 only results in 0 or 1, and 0 is considered a false value in a boolean test. I also used the sum() function to add up all the numbers that takewhile does pass through.
You don't need to keep track if you found or not the first even number, just break and leave the for loop when you find it:
for num in L:
if num % 2 != 0:
total = total + num
else:
break

Categories

Resources