Having trouble using the sum function - python

The input (list) would be a list similar to [[1,2],[5,6],[4,6]]. I am trying to add the whole row together to test if it is even or odd.
def evenrow(list):
for row in list:
for item in row:
newNums+=item
n=sum(newNums)
print(n)

First of all do not use 'list' as variable name. Second you calling sum for int value not for a list and that's why you getting error. Check your code please.
Not sure but your code can looks like:
def evenrow(list):
for row in list:
value = sum(row)
if values is even: # put your condition here
# do something
else:
print "Value is odd"

Just an alternate method:
def evenrow(lst):
return sum(map(sum,lst))%2 == 0 #True if even, False otherwise.
This works this way:
The outer sum adds up all items of the map, which applies sum to each item in lst. In python2, map returns a list object, while in python3, it returns a map object. This is passed to the outer sum function, which adds up all items in your map.
def evenrow(lst):
return sum(itertools.chain(*a)) % 2 == 0
This expands all the items in a (each of the sublists), and chains them together, as a chain object. It then adds together all the items and determines if the sum is even.

You don't need the following line of code: n=sum(newNums). You already summed up all the items of row in the newNums += item line. Second, you have to declare newNums before using it in your code. So, the fixed version of code will look like this:
def evenrow(list):
for row in list:
newNums = 0
for item in row:
newNums += item
print(newNums)
BTW: You should consider accepting answers to some of your previous questions, otherwise nobody will spend their time to answer your new questions.

Related

loop with strange return function?

I have a question about the below code, particularly the 6th line; is it right to say that it is returning the index of target-nums[I]? If so, why is there another I after it?
Also, what is comp[nums[I]] = I doing? Is it assigning values of nums into comp if it is not in comp already?
Finally, what is the final return [ ] doing in the last line of code?
def TwoSum(nums, target):
comp = {}
for i in range(len(nums)):
if (target - nums[i]) in comp:
return [comp[target - nums[i]],i]
comp[nums[i]] = i
return []
print(TwoSum(nums,target))
is it right to say that it is returning the index of target-nums[I]?
If so, why is there another 'I' after it?
It is returning a list of two items, the first item being comp[target - nums[i]], and the second item being i. It's the same idea as:
def addAndSubtract(x, y):
return [x+y, x-y]
Above, we return a list, the first item in the list is the value of evaluating x+y and the second value is the result of evaluating x-y.
Also, what is comp[nums[I]] = I doing? Is it assigning values of nums into comp > if it is not in comp already?
This will assign the value of nums[i] as a key in your comp dictionary and assign it the value of i. It essentially stores the current value in nums and along with its index. This does two things:
Allows you to easily and quickly check if you have seen a given number yet by checking if it is a key in your comp dictionary
Allows you to check where that number was last seen in your list.
The comp[nums[i]] = i occurs each time your for loop runs, so it will do it for all numbers, in your list, unless it returns in your if-statement. If you happen to encounter the same number again (which is already in your list), then this assignment will simply overwrite the value with the current index of the current number (ie: i).
Finally, what is the final return [ ] doing in the last line of code?
The purpose of this is to return an empty list. It is just a way to signify that no result was found. You will only reach that return when you have iterated through all the numbers in your list and not returned from within your for loop, thus indicating no sum can be made to reach the target.
I explain how this algorithm works in detail here, so you might want to check that out if you need more of an explanation. Although the question is a JavaScript question, the logic explained is the exact same as this.

sub-sum from a list without loops

So i'm studying recursion and have to write some codes using no loops
For a part of my code I want to check if I can sum up a subset of a list to a specific number, and if so return the indexes of those numbers on the list.
For example, if the list is [5,40,20,20,20] and i send it with the number 60, i want my output to be [1,2] since 40+20=60.
In case I can't get to the number, the output should be an empty list.
I started with
def find_sum(num,lst,i,sub_lst_sum,index_lst):
if num == sub_lst_sum:
return index_lst
if i == len(sum): ## finished going over the list without getting to the sum
return []
if sub_lst_sum+lst[i] > num:
return find_sum(num,lst,i+1,sub_lst_sum,index_lst)
return ?..
index_lst = find_sum(60,[5,40,20,20,20],0,0,[])
num is the number i want to sum up to,
lst is the list of numbers
the last return should go over both the option that I count the current number in the list and not counting it.. (otherwise in the example it will take the five and there will be no solution).
I'm not sure how to do this..
Here's a hint. Perhaps the simplest way to go about it is to consider the following inductive reasoning to guide your recursion.
If
index_list = find_sum(num,lst,i+1)
Then
index_list = find_sum(num,lst,i)
That is, if a list of indices can be use to construct a sum num using elements from position i+1 onwards, then it is also a solution when using elements from position i onwards. That much should be clear. The second piece of inductive reasoning is,
If
index_list = find_sum(num-lst[i],lst,i+1)
Then
[i]+index_list = find_sum(num,lst,i)
That is, if a list of indices can be used to return a sum num-lst[i] using elements from position i+1 onwards, then you can use it to build a list of indices whose respective elements sum is num by appending i.
These two bits of inductive reasoning can be translated into two recursive calls to solve the problem. Also the first one I wrote should be used for the second recursive call and not the first (question: why?).
Also you might want to rethink using empty list for the base case where there is no solution. That can work, but your returning as a solution a list that is not a solution. In python I think None would be a the standard idiomatic choice (but you might want to double check that with someone more well-versed in python than me).
Fill in the blanks
def find_sum(num,lst,i):
if num == 0 :
return []
elif i == len(lst) :
return None
else :
ixs = find_sum(???,lst,i+1)
if ixs != None :
return ???
else :
return find_sum(???,lst,i+1)

my python code is not working.....i want to find if the entered list contains duplicate items

I want to use this function to find duplicate items in my list, but this code is not working:
p = "enter a list\n"
t = raw_input(p)
def has_duplicate(t):
o = sorted(t)
i = 0
while i < len(o):
if o[i] == o[i + 1]:
print "the list has duplicates"
elif o[i] != o[i+1]:
i += 1
if i >= len(o):
print "the list has no duplicate"
It gives me an error saying has_duplicates not defined.
As #mgilson commented, your issue is you are calling the function incorrectly (has_duplicates vs has_duplicate) however...
The most straight forward way to do this is using a set and comparing len.
def has_duplicates(t):
return len(set(t)) != len(t)
If you take an iterable and wrap it in a set you will end up with only unique items. If the length of the set is the same as your original iterable then you have no duplicates. If the length is different (will always be equal to or smaller) then you have duplicates which were removed when converting to a set type.
First thing is you do list_name.sort().
Other easy way to find duplicates is
len(your_list)!=len(set(your_list))
you might be calling function has_duplicates but you have defined has_duplicate function.
try to call has_duplicate

Why wont my code work for a single list but works for a nested list?

The first print system work when there are multiple lists passed into the function. However, when passing in only a single list, I get the error "AttributeError: 'int' object has no attribute 'pop'"
This code is attempting to remove one item from the list to see if that popped item still exists in the remaining list.
def check_row(p):
for e in p:
while e:
x = e.pop()
if x in e:
return False
return True
print check_row([[8,2,3,4,5],
[2,3,1,5,6],
[4,0,2,3,1]])
print check_row([1,2,3,4,5])
Many thanks.
You are popping the item from the element, not the outer list. If your elements are not lists, then don't try to treat them as such.
You cannot, however, remove items from the outer list while at the same time looping over it, and expect the loop to not jump items.
If you want to see if an item occurs more than once in the list, compare the length of the set() of the list instead:
def check_row(row):
return len(row) == len(set(row))
This only works for hashable values, which nested lists are not, but at the very least does not alter the list in place, as your code would do.
You could still use a list scan, but then at least use list.index() to limit the search to a start index beyond the current position:
def check_row(row):
for i, elem in enumerate(row):
try:
row.index(elem, i + 1)
return False # dupe found
except ValueError:
pass # no dupe found
return True
However, this assumes you wanted to only test the outer list for duplicates. Supporting a nested structure and flat structures in the same code without more details on what you expect to happen in each case is much more complicated.
In the case of a single (non-nested) list, you're calling .pop() on elements (e) which aren't lists and therefore presumably don't have a .pop method.
That's because e is an element of your list. In the nested one, e is a list, while in the second one, e is an integer. Therefore, e.pop is invalid for the second one.
You'll have to make it always nested:
>>> print(check_row([[1, 2, 3, 4, 5]]))
True
This way, the value passed to check_row is always a nested list, even if it has only one element.
But as far as checking if the elements are still in the other lists, i would firstly flatten the list, and then check if there are duplicate elements in the list.
import collections
def flatten(l):
for el in l:
if isinstance(el, collections.Iterable) and not isinstance(el, str):
for sub in flatten(el):
yield sub
else:
yield el
def check_row(p):
flat = list(flatten(p))
return len(flat) == len(set(flat))
This way, check_row will always produce the result you wanted, ignoring the fact it's a list or nested list :)
Hope this helps!
You're confusing yourself with your naming. The function you called check_row actually checks a list of rows, despite the name, so passing it a single row fails. The fact that you're using meaningless one-letter names doesn't help either. Let's rewrite it more clearly:
If you want a function that checks a single row,
def check_rows(rows):
for row in rows:
while row:
element = row.pop()
if element in row:
return False
return True
Now it should be clearer why it fails: You're passing it a single row as the rows, so for row in rows is getting the elements rather than the rows, and it all goes downhill from there.
What you probably want is a check_row function that works on a single row, and then a check_rows that calls check_row on each row:
def check_row(row):
while row:
element = row.pop()
if element in row:
return False
return True
def check_rows(rows):
for row in rows:
if not check_row(row):
return False
return True
But really, I don't know why you want this function at all. It destructively modifies the rows, removing every element up to the first duplicate. Why would you want that? For example, Martijn Pieters's solution is simpler and more efficient, as well as being non-destructive:
def check_row(row):
return len(set(row)) == len(row)
And while we're at it, let's use the all function instead of an explicit loop for check_rows:
def check_rows(rows):
return all(check_row(row) for row in rows)

Loop in a list (Python v3) beginner

I am stuck in making a loop that will eliminate the values(from the alist) that are below average.
Thanks for the help.
a=input("Enter a list of values separated by a coma : ")
alist=eval(a)
print("the list is : ",alist)
average = sum(alist)/len(alist)
print("the average is : ",average)
for i in alist:
if alist[i]<average:
alist.remove[i]
You are almost there. Instead of removing elements, select elements you want to retain instead:
alist = [a for a in alist if a>=average]
Your mistake here is that for i in alist: is iterating over list elements themselves, not indexes, so alist[i] is throwing an error (or returning nonsense).
For the "loop" you can use a filter and a lambda function.
above_average = list(filter(lambda x: x >= average, alist))
For the rest of your code, I suggest you clean it up to something which is safer (use of eval is very bad)
import ast
user_string = raw_input('input a list of numbers separated by a commas: ')
alist = list(ast.literal_eval(user_string)))
So, in all, I would write your code as something like this:
import ast
user_string = raw_input('input a list of numbers separated by a commas: ')
numbers = list(ast.literal_eval(user_string)))
average = sum(numbers)/len(numbers)
print('The numbers: {}'.format(numbers))
print('The average: {}'.format(average))
above_average = list(filter(lambda x: x >= average, numbers))
# now do what you want with the above_average numbers.
Other answers tell you how to do it. I'll tell you why it doesn't work:
You iterate over the list and, at the same time, modify it.
This leads to items being missed during the iteration.
Why?
Internally, the iteration works via an index to the list. So it is the same as doing
idx = 0
while True:
try:
i = alist[idx]
except IndexError:
break
idx += 1
if alist[i] < average:
alist.remove(i)
What happens if you are at the element #3, go to the next one and then remove #3? Right, the indexes of the remaining ones move down and you are pointing to the one which formerly was #5. The old #4 is skipped at this test.
(BTW, I don't know if you noticed, I have replaced your [] behind .remove with ().)
You are mixing two ways of iterating a list: By index, and by element. In your loop, i is not the index, but the element of the list itself, thus alist[i] won't work.
If you use the for x in somelist loop, then x is the element itself, not the index of the element. For iterating over the indices, you can use for i in range(len(somelist)), or you could use for i, x in enumerate(somelist) to loop over tuples of index and element.
Also note that removing elements from a list or other kinds of collections while you are looping them generally is a bad idea. Better create a copy of the list.
for x in list(alist): # creates a copy of alist
if x < average: # remember: x is the element itselt
alist.remove(x) # remove element x from list
But the way you do it (with eval of a comma-separated string of numbers), alist is a tuple, not a list, and thus has no remove method at all. Thus you either have to convert it to a list before (alist = list(eval(a)), or use one of the approaches given in the other answers, creating a new list using list comprehension or filter and retaining the "good" elements.
As a general principle for asking StackOverflow questions like this, you should always include example input and output -- show what happens, and what you expect to happen.
In this case, I believe there are two three problems with your code:
Edit: Third, but possibly most importantly, look at glglgl's answer. If you implement the two fixes I describe below, you'll still have one problem: your code won't necessarily remove all the items you want to remove, because it'll skip over some items.
First, you say alist[i], which grabs the element of alist at index i. But saying for i in alist makes i be successive elements in the list already. Example:
mylist = [1, 2, 4]
for i in mylist:
print(i)
Would give you the output:
1
2
4
If you instead said this (which is like what you wrote)
mylist = [1, 2, 4]
for i in mylist:
print(mylist[i])
It wouldn't work as you'd expect, because you'd get the element at index 1, the element at index 2, and then try to get the element at index 4, but that wouldn't exist. You'll get something like this:
2
4
IndexError: list index out of range
Second, your syntax for removing an element is wrong. You should use alist.remove(i) instead of alist.remove[i]. You want to call a function, so you use parentheses. The square brackets are for indexing and slicing.

Categories

Resources