list compression weird behavior [duplicate] - python

This question already has answers here:
List comprehension with if statement
(5 answers)
Closed 3 years ago.
I have question about list comprehension. If I want to output the odd squared numbers and put the condition in the output part (I know how to put condition in the loop part to get the desired result)
[num**2 if num % 2==0 for num in range(10)]
returned an error code. Why Python doesn't like it?
By adding else, the following returns zeros
[num**2 if num % 2==0 else 0 for num in range(10)]
so I tried to remove zeros on top of this
[num**2 if num % 2==0 else 0 for num in range(10)].remove(0)
and python returned empty, why?

[num**2 if num % 2==0 for num in range(10)] returned an error code. Why Python doesn't like it?
You have the list comprehension syntax backwards. The for comes first, then the if.
[num**2 for num in range(10) if num % 2 == 0]
Alternatively, use range’s step parameter:
[num**2 for num in range(0, 10, 2)]

The list comprehension is out of order.
A list comprehension consists of brackets containing an expression
followed by a for clause, then zero or more for or if clauses. -- Python, Data Structures Documentation, List Comprehensions
Change your first one to:
[num**2 for num in range(10) if num % 2 == 0]
output:
[0, 4, 16, 36, 64]

Related

Python adding to a nested list [duplicate]

This question already has answers here:
Why does this iterative list-growing code give IndexError: list assignment index out of range? How can I repeatedly add (append) elements to a list?
(9 answers)
Closed 4 months ago.
n = int(len(network))
num=[]
for i in range(n):
for j in range(n):
num[i].append(int (between_lists(network[i],network[j])))
return num
this error message I get
num[i].append(int (between_lists(network[i],network[j])))
IndexError: list index out of range
Any of your three indexing operations could be the cause, but num is definitely an empty list, so you can't index it at all. Did you perhaps mean to append to num itself, not to a sublist within num (which has no inner lists at all)?
num.append(int (between_lists(network[i],network[j])))
# ^ removed [i]
Update: Based on your comments, you want a new sublist for each run of the outer loop, so what you really wanted is:
for i in range(n):
num.append([]) # Put in new sublist
for j in range(n):
num[i].append(int(between_lists(network[i],network[j])))
return num

Python basic question which i really cant understand the logic [duplicate]

This question already has answers here:
Understanding this Python code from 2014's new year challenge
(6 answers)
Generator expression evaluation with several ... for ... in ... parts
(2 answers)
Explain python list comprehension technique
(2 answers)
Closed 1 year ago.
def sum_five(l):
return sum(num for num in l if num > 5)
#desired outcome:
#sum_five([1, 5, 20, 30, 4, 9, 18]) ➞ 77
#sum_five([1, 2, 3, 4]) ➞ 0
#sum_five([10, 12, 28, 47, 55, 100]) ➞ 252
gotten this as a solution. The question is to loop through a list and sum up those that are less than 5. This is the cleanest and shortest answer which i really loved to learn. Can anyone explain in very simple English to me what does the num for num in l if num > 5 really means?
And give me more examples to understand that logic so i can next time apply it? PS: i can do the outcome using for loop and if statement already, i just want to learn how to use this one liner. Thanks.
This is known as Generator Expression which gives you another list which means like this:
FOR any element which we call it num, in the list which we call it l, if this element(num) is greater than 5, take it and put it in result list.
For example for [1,2,3,4] there is no number greater than 5, so the result is [] which has the summation equal to zero.
Another example is [1,5,20,30,4,9,18] which has the result equal to [20,30,9,18] which has the summation equal to 20+30+9+18 = 77
The list comprehension -- any list comprehension -- can be written as a for loop remembering that it returns a list (meaning you don't have to write the part that assigns the result to a list which in this case I've called out). That's a good thing because that list you are taking the sum of and returning that result instead.
out = []
def sum_five(l):
for num in l:
if num > 5:
out.append(num)
else:
continue
return sum(out)
The general form a list comprehension is worth going into more. But I'm going to strip out some of the code to this for clarity
for num in l:
if num > 5:
num
Goes to this:
for num in l if num > 5:
num
And then to this:
num for num in l if num > 5:
We don't need that colon at the end and the whole thing gets put in braces because that's what specifies a list is getting returned. That leaves us with:
[num for num in l if num > 5]
You then take the sum of that list:
sum([num for num in l if num > 5])
You'll notice the formatting is a bit different than for the loop. If it was just a long no one would use it.

Problems getting code to repeat/work for each value in list [duplicate]

This question already has answers here:
Why do I get an IndexError (or TypeError, or just wrong results) from "ar[i]" inside "for i in ar"?
(4 answers)
Apply function to each element of a list
(4 answers)
Accessing the index in 'for' loops
(26 answers)
Closed 5 months ago.
I'm having problems getting my code to work appropriately for each value in a list.
The purpose of the code is to create a function which has an input argument numList, a list. The function replaces every odd number in the list with 0 and return the new list.
def onlyEvens(numList):
for onlyEvens in numList:
if onlyEvens % 2 != 0:
numList[onlyEvens] = 0
return numList
print(onlyEvens([ 1, 5, 2, 3, 4 ]))
It outputs [1, 0, 2, 3, 4] however the desired output is [0, 0, 2, 0, 4]. Where did I go wrong?
Solution
You can solve your issue as follows:
def onlyEvens(numList):
for i in range(len(numList)):
if onlyEvens % 2 != 0:
numList[i] = 0
return numList
Explanation
The problem lies within your 3rd line of code: numList[onlyEvens]. onlyEvens is an element in the list and not an index. What does that mean? See the examples below.
Example 1
Code
list = ['a', 'b', 'c']
for letter in list:
print(letter)
Output
'a'
'b'
'c'
Example 2
Code
list = ['a', 'b', 'c']
for i in range(len(list)): # Repeat it as many times as the length of list.
print(i)
Output
0
1
2
You're using onlyEvens as an index to numList, instead of using the actual index of onlyEvens. You're also returning immediately instead of after going through the whole list, because of the indentation of your return. One solution for getting the index of each onlyEvens is to use enumerate:
def onlyEvens(numList):
for i, onlyEvens in enumerate(numList):
if onlyEvens % 2 != 0:
numList[i] = 0
return numList
print(onlyEvens([ 1, 5, 2, 3, 4 ]))
Output:
[0, 0, 2, 0, 4]
For more info on enumerate: https://docs.python.org/3/library/functions.html#enumerate
Using onlyEvens as the name of both a function and a variable in that function is confusing and error-prone. I'd suggest changing that. Also notice that you return inside your loop so you'll return after processing the first element. So move that outside your loop.
Let's also add a print statement to help debug. So let's say your code now looks like:
def onlyEvens(numList):
for num in numList:
if num % 2 != 0:
print('Found a odd number:', num)
numList[num] = 0
return numList
If you run that you'd see that it first processes 1, the first number in the list and, since that's odd, you'd see Found an odd number: 1. Now look at the next line: you use that as an index into numList But the index of 1 in that list isn't 1 - it's 0 so you end up replacing the wrong element. Try changing your loop to something like:
for i, num in enumerate(numList):
and I think you'll be able to solve it from there.

How to add up the numbers 1 through "n" and print out the result? [duplicate]

This question already has answers here:
Sum of the integers from 1 to n
(11 answers)
Closed 5 years ago.
I have written the following code for an exercise I was given, nonetheless, when I try to submit it, I get an incorrect answer for my code.
So this is my code:
def problem(n):
my_sum = 0
while my_sum < n:
my_sum = n
my_sum = my_sum + n
print (my_sum)
What they have asked me to code is the following: Write a function problem(n): that adds up the numbers 1 through n and
prints out the result. You should use either a 'while' loop or a 'for' loop.
Be sure that you check your answer on several numbers n.
You can try this:
def problem(n):
print sum(xrange(1, n+1))
If you are not allowed to use the built in sum function, you can try this:
def problem(n):
counter = 0
for i in range(1, n+1):
counter += i
print counter
The top example uses a for loop in what is called list comprehension, which is a shorter way of utilizing the regular for loop.
Your solution will iterate through the while loop only once and when my_sum becomes >= to n it will stop.
What you need is:
for x in range(1, n+1):
my_sum += x
This will do the job. n+1 is done because the right boundary of range() is non-inclusive.

For loops and else statements in Python

I am using some conditional for loops within the jinja2 template framework for python. I'm wondering if there's a way to do the same thing but outside of jinja2, similar to:
{% for i in a if i == 1 %}
{{ i }}
{% else %}
no items
{% endfor %}
When I try this in plain ol' python, it doesn't like it
>>> for i in a if i == 1:
SyntaxError: invalid syntax
What I'd like to be able to do is something like this:
for i in a if i == 1:
print i
else:
print 'no matches found'
You're already very close, all that is needed is a list comprehension that forms a list with only the values of a that are equal to 1.
In python the for..else statement is valid as well.
for i in [x for x in a if x == 1]:
print i
else:
print 'no matches found'
This will print all the values in a that are 1, unless none were found. Then it prints no matches found
As mentioned by davidism, to prevent an intermediate evaluation of the entire list, you can use a generator instead of a LC:
for i in (x for x in a if x == 1):
print i
else:
print 'no matches found'
You can use else blocks with loop statements. If the loop flow isn't disturbed by statements such as break, it falls to the else block. I included a simple prime number finder below:
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print n, 'equals', x, '*', n/x
break
else:
# loop fell through without finding a factor
print n, 'is a prime number'
Output:
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3
Note: If you combine for / else statements with list comprehensions you can accomplish what you want.
Simple list comprehension:
# For generating a list of odd numbers from 1 to 10
[n for n in range(1, 10) if n % 2 == 1]
# Generator version preventing evaluation of the whole list at once.
(n for n in range(1, 10) if n % 2 == 1)
That way you'll generate an iterable container with list comprehension method and iterate it using a for / else loop:
for n in [n for item_container if n == 1]
# Do work
pass
else:
# Loop falls through if the flow isn't disturbed
# Do some other work
pass
Edit: What you are asking is simply checking whether an element is in a container or not and then executing statements. It is terribly inefficient. You can do that much faster using set data structure in CPython(Python's most common implementation).
Your code has O(n) complexity at average and worst case.
set member check will have O(1) at average and O(n) at worst(dictionary has a similar implementation).
So the following code will be much faster:
element = 9
container = set(range(1, 10))
print("Match Found." if element in container else "Match Not Found.")
For more information check below:
Python Control Flow
Python List Comprehension
Python Set
If you just want the values in a list:
items = [i for i in a if i == 1]
To print out, including a note if there are no matches:
for i in items:
print i
if not items:
print 'no matches found'

Categories