2

I am trying to fill up my matrix with zeros. Unfortunatelly, in the following example, variables x and y are redundand:

self.matrix = [[0 for x in range(0, self.N)] for y in range(0, self.N)]

Multiplying list, copy only references what of course is not what I am expecting:

>>> matrix = [[0] * 5] * 5
>>> matrix
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> matrix[1][1] = "X"
>>> matrix
[[0, 'X', 0, 0, 0], [0, 'X', 0, 0, 0], [0, 'X', 0, 0, 0], [0, 'X', 0, 0, 0], [0, 'X', 0, 0, 0]]

So, is there any solution using a list comprehension to avoid redundand variables (x & y)?

IProblemFactory
  • 9,551
  • 8
  • 50
  • 66
  • 1
    @Ashwini: How is that helpful? – Niklas B. Apr 01 '12 at 00:07
  • If I am not wrong then his problem is that when he's adding a value to a particular list item, it is also getting added to the other lists inside the list named matrix. and http://stackoverflow.com/a/8713681/846892 explains this behaviour of lists. – Ashwini Chaudhary Apr 01 '12 at 00:13
  • 2
    @AshwiniChaudhary: He knows about that behaviour. The question is an entirely different one, though... – Niklas B. Apr 01 '12 at 00:13

2 Answers2

5

The common idiom is to assign the result to the variable _, which signals a possible reader of your code that the value will not be used:

[[0]*self.N for _ in range(self.N)]

As you see, we can use the [0]*size idiom for the inner list because 0 is an immutable value. Also, you can call range with only one argument, in which case it is treated as the upper bound, with 0 being the lower bound).

If you want, you can build yourself a list build helper that supports creating lists of arbitrary nesting depth:

def make_multi_list(dim, func):
  if not dim: return func()
  return [make_multi_list(dim[1:], func) for _ in range(dim[0])]

Usage:

>>> make_multi_list((2, 2), lambda: 0)
[[0, 0], [0, 0]]
>>> make_multi_list((3, 2, 1), lambda: 0)
[[[0], [0]], [[0], [0]], [[0], [0]]]
Niklas B.
  • 92,950
  • 18
  • 194
  • 224
1

Alternatively, you could do:

from itertools import repeat

self.matrix = [list(repeat(0, self.N)) for _ in range(0, self.N)]
Simeon Visser
  • 118,920
  • 18
  • 185
  • 180
  • 1
    Thanks, you're right. I've fixed the code. Using the repeat function isn't necessary when the language already supports this feature. – Simeon Visser Apr 01 '12 at 00:05