iradel.1618
iradel.1618

Reputation: 3

Python: Using sum() on a list of ints

I'm working on a simple python script that takes a number, converts it to binary, and returns the sum of the binary digits. Here is what I have so far.

#!/usr/bin/python

def sum2(n):
    a = str(bin(n))
    b = a.replace('0b', '')
    return sum([map(int, x) for x in b])

n = int(raw_input("Input number>"))
print sum2(n)

In plain English I take n and convert it to binary, and then convert it to a string. I chop off the 0b (from bin()) and convert the binary characters into a list of ints and then attempt to sum() them.

When trying to figure out how to add the digits together I googled around and found that I should be able to sum() a list of ints. When I attempt to do this, I end up with this traceback.

Traceback (most recent call last):
  File "D:\scripts\sum2n1.py", line 9, in <module>
    print sum2(x)
  File "D:\scripts\sum2n1.py", line 6, in sum2
    return sum([map(int, x) for x in b])
TypeError: unsupported operand type(s) for +: 'int' and 'list'

So I find out sum() needs an "iterable" to do it's job. I google around and find there's an iter() function I can call, but it doesn't seem to work.

There's also __iter__() which doesn't work either.

Can anyone tell me what I'm doing wrong? I'm still quite a bit of a beginner. Thanks in advance.

(And no, it's not my homework.)

Upvotes: 0

Views: 6187

Answers (7)

Levon
Levon

Reputation: 143022

This works:

def sum2(n):
    idx = 3 if n < 0 else 2 # adjust index for slice based on neg/pos number
    a = bin(n)[idx:]        # doesn't assign the '0b' (or '-0b' for negatives)

    return sum(int(i) for i in a)  # convert chars into ints and sum

Note, using slice notation to eliminate the leading '0b' or '-0b' is preferable to using replace().

You can use list comprehension, or a generator expression for this.

Update:

In a helpful comment @DSM pointed out that negative numbers have '-0b' in front of the binary string, I updated the code to deal with this by adjusting the slice based on the sign of the number.

Upvotes: 3

Vinayak Kolagi
Vinayak Kolagi

Reputation: 1881

One using reduce :

ans = reduce(lambda x,y:int(x)+int(y), L)

Upvotes: 0

John La Rooy
John La Rooy

Reputation: 304205

Why not simply

def sum2(n):
    return sum(x=='1' for x in bin(n))

or even more simply

def sum2(n):
    return bin(n).count('1')

Upvotes: 6

mhawke
mhawke

Reputation: 87084

Don't wrap the map call in the list comprehension.

Instead of

return sum([map(int, x) for x in b])

Do this:

return sum(map(int, b))

Upvotes: 1

Gabe
Gabe

Reputation: 86718

You are combining list comprehensions with the map function, in an apparent attempt to do the same thing twice. You want either:

sum(int(x) for x in b)

or

sum(map(int, b))

Upvotes: 5

BrenBarn
BrenBarn

Reputation: 251398

By doing [map(int, x) for x in b], you are doing the same thing twice. map(int, b) would make each digit an int. Or [int(x) for x in b] would do the same. But you are doing both. Pick one or the other. Try:

sum([int(x) for x in b])

Upvotes: 2

Joran Beasley
Joran Beasley

Reputation: 113988

try doing this instead on your return

return sum(map(int,b))

that should work

Upvotes: 2

Related Questions