tags:

views:

53

answers:

3

I want to calculate the center-of-mass using the map function. I don't want to use for loops. Help with bottom two lines?

class Obj():  
    def __init__(self, mass = 0., x = 0., y = 0.):    
        self.mass = mass    
        self.x = x    
        self.y = y    

# Create List of Objects    
objList = []
n = 0    
for i in range(0,10):    
    for j in range(0,10):    
        objList.append(Obj(i*j,i,j))    

# Calculate Center of Mass of List
# The following is pseudocode, does not actually work
SumOfMass = sum(objList[:].mass)       
CenterOfMassX = sum(objList[:].x.*objList[:].mass)/SumOfMass    
+1  A: 
sumofmass = sum(i.mass for i in objList)
centre = sum(i.x * i.mass for i in objList)/sumofmass

also, you could populate your objList like this:

objList = [Obj(i*j, i, j) for in range(10) for j in range(10)]

Note, that range takes only integer arguments.

P.S. map is a for loop.

SilentGhost
it's a for loop in py2k only. In py3k it's an iterator-maker.
John Machin
`map` is a higher-level function.
intuited
@intuited: is it? ok. and?
SilentGhost
@John: it's a for loop in a sense that it iterates over each element of the iterable.
SilentGhost
So it's syntactically distinct from a for loop in that you have to pass functions to it rather than using a bound variable in an expression.
intuited
@intuited: why does it matter? that's not what my comment is about.
SilentGhost
@SilentGhost: Well, it doesn't, necessarily. But one reason people decide to avoid using for loops is in order to get more practice with thinking about things in terms of functions, and in using higher-level functions like `map`, `reduce`, etc. So if this is the OP's reason for wanting to avoid for loops, then it is relevant.
intuited
@SilentGhost: NO, it makes an iterator (a map object) that does the iterating when you incite it ... it's a two-stage process, geddit??
John Machin
@John: and it does iterating with the freaking `for` loop, not with some out-world magic. Geddit?
SilentGhost
@John: and please there is no need to start a flame war, when **your answer clearly says that `map` returns a list**. Fix your answer first, please.
SilentGhost
@SilentGhost: fixed my answer. Back to the point: """map is a for loop""" -- no, in py3k map() [that's the result of invoking map] is an iterator that performs a for loop when you ask it to. `it = map(func, stuff); results = list(it)`
John Machin
+1  A: 

You can't do the last two lines unless you abandon your anti-for prejudice.

SumOfMass = sum(obj.mass for obj in objList)       
CenterOfMassX = sum(obj.x * obj.mass for obj in objList)/SumOfMass 

With py2k (which are you using?), map(func, alist) is equivalent to [func(v) for v in alist] i.e. it returns a list. You need two scalar answers, not one or two vectors. What func did you have in mind? Why do you want to calculate the center of mass using the map function?

John Machin
it returns a list in py2k only
SilentGhost
right, in py3k you have to write list(map()) if you want a list ;)
Ant
+1  A: 

If you are really dead set against using for, you can use the attrgetter function from the operator module. E.G.:

from operator import attrgetter
mass_of = attrgetter('mass')
SumOfMass = sum(map(mass_of, objList))

However, doing so runs contrary to the dictates of Python style (as does using camelCase variables — normally you name them like_this). It's more or less acceptable to use map if the thing you need to access is already in the form of a function which takes the sequence element as its only parameter. In other words, if you can call map(some_function, sequence) without having to jump through any hoops like those above to get some_function, then it's okay.

For other situations (which is most of them), it's considered preferable or mandatory to use a list-comprehension style as exemplified in some of the other answers.

intuited
`SumOfMass = map(mass_of, objList)` -- Looks like you're missing a `sum()` sumwhere.
John Machin
Nicely summed up.
intuited