1

I'm trying to remove the last 2 digits of each item in the list below.

keys = ['2013', '1101', '1201', '1301', '1401', '1402', '1403', '2100', '2150', '3201', '5201', '5301', '9810', '9820', '9830', '2013', '1101', '1201', '1202', '1301', '1304', '1401', '1402', '1403', '2100', '2150', '3401', '5201', '5301', '9810', '9820', '9830', '2013', '1101', '5201', '2013', '1101', '1201', '1401', '1402', '1403', '2100', '5201', '5301', '5402', '9810', '9820', '9830', '2013']

for n,k in keys:
  keys[n] = keys[n][0]+keys[n][1]

I keep getting the ValueError: too many values to unpack

OOrion
  • 85
  • 4
  • 8

2 Answers2

5

No need for a regex here ... simple slicing will do the trick:

keys = [k[:-2] for k in keys]

This isn't actually in place, but it can be made in place easily:

keys[:] = [k[:-2] for k in keys]
mgilson
  • 300,191
  • 65
  • 633
  • 696
  • "but it can be made in place easily" - I think you should say how :) – Fredrick Brennan Feb 28 '13 at 21:13
  • 1
    `keys[:]` *acts* like it is in place and *functionally* seem like it -- but [it is not](http://stackoverflow.com/a/4948508/648852) –  Feb 28 '13 at 21:21
  • @Pyson -- That's a very minor nitpick. I *am* changing `keys` in place even if I am creating an intermediate list to do so. Of course you could change it to a generator expression, but I happen to like the symmetry in the statement when memory isn't usually an issue. In fact, that link you posted doesn't state anything about whether the keys list is modified in place. It only talks about the extra memory involved with doing it this way. If memory is really a problem, use a loop (or a genexp on the rhs and a python implementation that doesn't make it a tuple first) – mgilson Feb 28 '13 at 21:22
  • It is not a minor nit if memory is scarce. Read the source code. Even you change it to a generator, a full intermediate tuple is generated before the assignment to keys[:] –  Feb 28 '13 at 21:28
  • @Pyson -- with Cpython, but there's no guarantee that other python implementations will behave the same. I'm just saying that this is in fact one way to update the `keys` list **in place**. It's not the most memory efficient way to do it, but to say that `keys[:] =` is not in place is just wrong. – mgilson Feb 28 '13 at 21:32
  • @Pyson: This is not about memory usage. If you have large lists, sure, worry about memory. This is about replacing a list in-place, where that list may be referenced elsewhere as well. – Martijn Pieters Feb 28 '13 at 21:32
  • Nice explanation. It helped me see the point. `a = []`..> `b=a` ..> `a=[]` then id(a) is not equal to id(b). `a = []`..> `b=a` ..> `a[:]=[]` then id(a) is equal id(b). – Octipi Feb 28 '13 at 22:19
  • @Martijn Pieters: I agree. –  Mar 01 '13 at 15:31
1

You are receiving an error because keys is a list of strings of length 4, so

for n,k in keys:

cannot work, as a string of length 4 cannot be unpacked to the 2 variables n and k.

Anyway, here's another alternative:

map(operator.itemgetter(slice(-2)), keys)
arshajii
  • 127,459
  • 24
  • 238
  • 287
  • 1
    Kudos for digging up `slice`. I was actually surprised when this worked. I would have written `map(itemgetter(slice(None,-2)),keys)` which I believe would have worked as well. – mgilson Feb 28 '13 at 21:20
  • And also, you *can* use sequence unpacking on strings just like you would on lists or tuples. (strings are sequences after all). That's why OP gets a "ValueError: **too many values to unpack** " instead of a `"TypeError: ... is not iterable" – mgilson Feb 28 '13 at 21:29
  • 1
    nice revision. +1 for explaining the actual exception raised. – mgilson Feb 28 '13 at 21:51