2

Given a list of floats spendList, I want to apply round() to each item, and either update the list in place with the rounded values, or create a new list.

I'm imagining this employing list comprehension to create the new list (if the original can't be overwritten), but what about the passing of each item to the round()?

I discovered sequence unpacking here so tried:

round(*spendList,2)

and got:

TypeError                                 Traceback (most recent call last)
<ipython-input-289-503a7651d08c> in <module>()
----> 1 round(*spendList)

TypeError: round() takes at most 2 arguments (56 given)

So surmising that round was trying to round each item in the list, I tried:

[i for i in round(*spendList[i],2)]

and got:

In [293]: [i for i in round(*spendList[i],2)]
  File "<ipython-input-293-956fc86bcec0>", line 1
    [i for i in round(*spendList[i],2)]
SyntaxError: only named arguments may follow *expression

Can sequence unpacking even be used here? If not, how can this be achieved?

Community
  • 1
  • 1
Pyderman
  • 14,809
  • 13
  • 61
  • 106
  • 1
    https://docs.python.org/2/library/functions.html#map ...or a list comprehension as you say – Anentropic Jul 03 '15 at 16:52
  • Related: http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-python-parameters – jonrsharpe Jul 03 '15 at 16:56
  • @Anentropic thanks, works. I needed to add a `lambda` to allow for the arguments that `round()` takes though: `map(lambda x: round(x,2), spendList)`. Can map handle these arguments itself somehow? – Pyderman Jul 03 '15 at 16:58
  • 1
    `spendList[:] = [round(1,2) for i in spendList]` will update the original object, you can also use a regular for loop using enumerate – Padraic Cunningham Jul 03 '15 at 17:00
  • @Pyderman yes you need the lambda like you did, or a generic way of adding a static argument to function call is https://docs.python.org/2/library/functools.html#functools.partial – Anentropic Jul 03 '15 at 17:13

3 Answers3

3

You have your list comprehension the wrong way around:

[i for i in round(*spendList[i],2)]

should be:

[round(i, 2) for i in spendList]

You want to iterate over spendList, and apply round to each item in it. There's no need for * ("splat") unpacking here; that's generally only needed for functions that take an arbitrary number of positional arguments (and, per the error message, round only takes two).

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • The most elegant solution. Had never before considered starting off a list comprehension with a function call. Nice. – Pyderman Jul 03 '15 at 17:05
2

You can use map() function for this -

>>> lst = [1.43223, 1.232 , 5.4343, 4.3233]
>>> lst1 = map(lambda x: round(x,2) , lst)
>>> lst1
[1.43, 1.23, 5.43, 4.32]

For Python 3.x , you need to use list(map(...)) as in Python 3.x map returns an iterator not a list.

Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
  • 2
    Note that, per [the introduction of the `map` iterator](https://docs.python.org/3/whatsnew/3.0.html#views-and-iterators-instead-of-lists) (emphasis mine): *"a quick fix is to wrap `map()` in `list()`, e.g. `list(map(...))`, **but a better fix is often to use a list comprehension**"*. – jonrsharpe Jul 03 '15 at 16:55
  • 2
    And in particular, if you're using a lambda with `map` then the list comprehension is likely to be more readable. `[round(x,2) for x in lst]` – Steve Jessop Jul 03 '15 at 17:00
  • @Anand I had just figured out that I needed `lamdba` or something similar to allow for the rounding; you just beat me to adding my a comment thereof. Thanks. – Pyderman Jul 03 '15 at 17:00
2

you could still use the list comprehension you talked aobut, just this way:

list = [1.1234, 4.556567645, 6.756756756, 8.45345345]
new_list = [round(i, 2) for i in list]

new_list will be: [1.12, 4.56, 6.76, 8.45]

elcn
  • 37
  • 2