Tutorial :Populate a list in python



Question:

I have a series of Python tuples representing coordinates:

tuples = [(1,1), (0,1), (1,0), (0,0), (2,1)]  

I want to create the following list:

l = []  for t in tuples:    l[ t[0] ][ t[1] ] = something  

I get an IndexError: list index out of range.

My background is in PHP and I expected that in Python you can create lists that start with index > 0, i.e. make gaps and then fill them up, but it seems you can't.

The idea is to have the lists sorted afterwards. I know I can do this with a dictionary, but as far as I know dictionaries cannot be sorted by keys. Update: I now know they can - see the accepted solution.

Edit: What I want to do is to create a 2D array that will represent the matrix described with the tuple coordinates, then iterate it in order. If I use a dictionary, i have no guarantee that iterating over the keys will be in order -> (0,0) (0,1) (0,2) (1,0) (1,1) (1,2) (2,0) (2,1) (2,2)

Can anyone help?


Solution:1

What do you mean exactly by "but as far as I know dictionaries cannot be sorted by keys"?

While this is not strictly the same as a "sorted dictionary", you can easily turn a dictionary into a list, sorted by the key, which seems to be what you're after:

>>> tuples = [(1,1), (0,1), (1,0), (0,0), (2,1)]  >>> l = {}  >>> for t in tuples:  ...    l[t] = "something"  >>> sorted(l) # equivalent to sorted(l.keys())  [(0, 0), (0, 1), (1, 0), (1, 1), (2, 1)]  >>> sorted(l.items()) # make a list of (key, value) tuples, and sort by key  [((0, 0), 'something'), ((0, 1), 'something'), ((1, 0), 'something'), ((1, 1), 'something'), ((2, 1), 'something')]      

(I turned something into the string "something" just to make the code work)

To make use of this for your case however (if I understand it correctly, that is), you would still need to fill the dictionary with None values or something for every "empty" coordinate tuple)


Solution:2

No, you cannot create list with gaps. But you can create a dictionary with tuple keys:

tuples = [(1,1), (0,1), (1,0), (0,0), (2,1)]  l = {}  for t in tuples:      l[t] = something  

Update: Try using NumPy, it provides wide range of operations over matrices and array. Cite from free pfd on NumPy available on the site (3.4.3 Flat Iterator indexing): "As mentioned previously, X.flat returns an iterator that will iterate over the entire array (in C-contiguous style with the last index varying the fastest". Looks like what you need.


Solution:3

You should look at dicts for something like that.

for t in tuples:    if not l.has_key(t[0]):      l[t[0]] = {}    l[t[0]][t[1]] = something  

Iterating over the dict is a bit different than iterating over a list, though. You'll have the keys(), values() and items() functions to help with that.

EDIT: try something like this for ordering:

for x in sorted(l.keys()):     for y in sorted(l[x].keys()):         print l[x][y]  


Solution:4

You create a one-dimensional list l and want to use it as a two-dimensional list. Thats why you get an index error.

You have the following options: create a map and use the tuple t as index:

l = {}  l[t] = something  

and you will get entries in l as:

{(1, 1): something}  

if you want a traditional array structure I'll advise you to look at numpy. With numpy you get n-dimensional arrays with "traditional" indexing.

As I mentioned use numpy,

with numpy you can create a 2-dimensional array, filled with zeros or ones or ... Tha you can fill any desired value with indexing [x,y] as you desire. Of course you can iterate over rows and columns or the whole array as a list.


Solution:5

If you know the size that you before hand,you can make a list of lists like this

>>> x = 3  >>> y = 3  >>> l = [[None] * x for i in range(y)]  >>> l  [[None, None, None], [None, None, None], [None, None, None]]  

Which you can then iterate like you originally suggested.


Solution:6

Extending the Nathan's answer,

tuples = [(1,1), (0,1), (1,0), (0,0), (2,1)]  x = max(tuples, key = lambda z : z[0])[0] + 1  y = max(tuples, key = lambda z : z[1])[1] + 1  l = [[None] * y for i in range(x)]  

And then you can do whatever you want


Solution:7

As mentioned earlier, you can't make lists with gaps, and dictionaries may be the better choice here. The trick is to makes sure that l[t[0]] exists when you put something in position t[1]. For this, I'd use a defaultdict.

import collections  tuples = [(1,1), (0,1), (1,0), (0,0), (2,1)]  l = collections.defaultdict(dict)  for t in tuples:      l[t[0]][t[1]] = something  

Since l is a defaultdict, if l[t[0]] doesn't exist, it will create an empty dict for you to put your something in at position t[1].

Note: this ends up being the same as @unwesen's answer, without the minor tedium of hand-checking for existence of the inner dict. Chalk it up to concurrent answering.


Solution:8

The dict solutions given are probably best for most purposes. For your issue of iterating over the keys in order, generally you would instead iterate over the coordinate space, not the dict keys, exactly the same way you would have for your list of lists. Use .get and you can specify the default value to use for the blank cells, or alternatively use "collections.defaultdict" to define a default at dict creation time. eg.

for y in range(10):      for x in range(10):          value = mydict.get((x,y), some_default_value)          # or just "value = mydict[x,y]" if used defaultdict  

If you do need an actual list of lists, you can construct it directly as below:

max_x, max_y = map(max, zip(*tuples))  l=[[something if (x,y) in tuples else 0 for y in range(max_y+1)]        for x in xrange(max_x+1)]  

If the list of tuples is likely to be long, the for performance reasons, you may want to use a set for the lookup,as "(x,y) in tuples" performs a scan of the list, rather than a fast lookup by hash. ie, change the second line to:

tuple_set = set(tuples)  l=[[something if (x,y) in tuple_set else 0 for y in range(max_y+1)]        for x in xrange(max_x+1)]  


Solution:9

I think you have only declared a one dimensional list.

I think you declare it as

l = [][]  

Edit: That's a syntax error

>>> l = [][]    File "<stdin>", line 1      l = [][]             ^  SyntaxError: invalid syntax  >>>   

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »