1

this is my first question on here. The question is simple -

# this removes the top list from the list of lists
triangle = [
[3, 0, 0],
[2, 0, 0],
[1, 0, 0]]
del triangle[0]

I want to have a similarly easy way to remove a 'column'. I can of course do this using a for loop, but is there something equivalent to

del triangle[0]

Thankyou

nebffa
  • 1,529
  • 1
  • 16
  • 26

2 Answers2

4

if you want to do this in place without copying the whole list, then something like

all(map(lambda x: x.pop(which_column), triangle))

EDIT. yes, it won't work if there's 0 in the column, just use any other accumulator function

sum(map(lambda x: x.pop(which_column), triangle))

for python 2 where map is not an iterator accumulator is not needed:

map(lambda x: x.pop(1), triangle)

as a side effect, this returns the deleted column which you may use

deleted_column = list(map(lambda x: x.pop(which_column), triangle))

(for python 2 list() wrapper is not needed)

A shorter form would be

sum(i.pop(which_column) for i in triangle)

or

deleted_column = [i.pop(which_column) for i in triangle]

Although I'm not sure if it qualifies as 'without for loop'

P.S. In official Python documentation they use 0-lenqth deque to consume iterators, like this:

collections.deque(map(lambda x: x.pop(which_column), triangle), maxlen=0)

I don't know if it's better than sum(), but it can be used for non-numeric data

panda-34
  • 4,089
  • 20
  • 25
  • This is actually the best option, not just because it accomplishes the task in one line. Raymond Hettinger's first method in fact modifies 'triangle' so it is no longer a list of lists and becomes a tuple (I may be saying some of this wrong as I am a fairly new user). Thereupon resulting in an error if the same procedure is performed on 'triangle' again. panda-34's code produces no such errors – nebffa Jul 01 '12 at 08:20
  • I like the terseness, but this won't work correctly. As soon as it hits a 0 value in the column, it stops removing elements. – Sean Johnson Jul 01 '12 at 08:20
  • Really? I'm actually using it to remove 0s and it's doing the job. – nebffa Jul 01 '12 at 08:22
  • @BenLucato, if it works for 0s for you, that means that map is not an iterator (in python 2 it wasn't (??)) in that case you don't need all() or sum() wrapper at all. – panda-34 Jul 01 '12 at 08:28
3

One way is to use zip() to transpose the matrix, delete the target row, and then zip it back:

>>> def delcolumn(mat, i):
        m = zip(*mat)
        del m[i]
        return zip(*m)

>>> triangle = delcolumn(triangle, 1)
>>> pprint(triangle, width=20)
[(3, 0),
 (2, 0),
 (1, 0)]

Another way is to use list comprehensions and slicing:

>>> def delcolumn(mat, i):
        return [row[:i] + row[i+1:] for row in mat]

>>> triangle = delcolumn(triangle, 1)
>>> pprint(triangle, width=20)
[(3, 0),
 (2, 0),
 (1, 0)]

One last technique is to mutate the matrix in-place using del:

>>> def delcolumn(mat, i):
         for row in mat:
             del row[i]
Community
  • 1
  • 1
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
  • 1
    Thankyou - though having something like triangle[:][0] to specify a column would still be the best - this is definitely right behind it. – nebffa Jul 01 '12 at 08:06
  • Note, however, that using a loop will be around twice as fast - http://pastebin.com/551BJ9Jx – DanielB Jul 01 '12 at 08:17