-1

I'm storing 2D coordinate pairs as the value in a dictionary. It seems to be treating them as integers (when I print them there are no quotation marks). Adding 10 to the value simply appends 10, however... so it's a tuple?

import random
d={}
num_points=8
def find_rand_points(num_points):
    for i in range(num_points):
        d[i]=(random.randrange(-250,251),random.randrange(-250,251))

d[0][0]=d[0][0]+[10]

I'm confused why they're tuples in the first place, because I thought randrange would return integers. I can see why it's not working though, since tuples are immutable. I'm trying to get them to add like an array, but am pretty new to Python.

fakedane
  • 95
  • 11

1 Answers1

1

Tuples are immutable objects in Python. This means that they cannot be changed once they are initialized. First how can you access this tuple?

Let's make your dictionary as follows

import random
d={}
num_points=8
for i in range(num_points):
    d[i]=(random.randrange(-250,251),random.randrange(-250,251))
print(d)

{0: (229, -137), 1: (178, 71), 2: (7, 19), 3: (180, 150), 4: (-126, -65), 5: (-235, 80), 6: (-174, -241), 7: (200, 16)}

Then to access one of these 2D points we can do

d[0]

(229, -137)

Then we can try and access the first number of this coordinate as

d[0][0]

229

But now lets try to change this value as

d[0][0] = d[0][0] + 10

--------------------------------------------------------------------------- TypeError Traceback (most recent call last) in () ----> 1 d[0][0] = d[0][0] + 10

TypeError: 'tuple' object does not support item assignment

This does not work. It tells us that a tuple does not support item assignment. It cannot be changed.


Use a list

You should instead use a list. Replace your ( ) to [ ] in the coordinate creation step.

import random
d={}
num_points=8
for i in range(num_points):
    d[i]=[random.randrange(-250,251),random.randrange(-250,251)]

Now we can do this and it will add 10 to the first dimension of the first coordinate.

d[0][0] = d[0][0] + 10

Use a numpy matrix

You can set each row to be each coordinate and then the columns represent the first and second value in the coordinate.

import numpy as np

num_points=8
d = np.zeros((num_points, 2))
for i in range(num_points):
    d[i,0], d[i,1]= random.randrange(-250,251), random.randrange(-250,251)

d[0]

array([-233., 92.])

d[0,1] += 100

array([-233., 192.])

JahKnows
  • 2,618
  • 3
  • 22
  • 37
  • 1
    Alternatively, you could keep using `tuple`s and do `d[0] = d[0][0] + 10, d[0][1]` (constructing a new `tuple` with the incremented value as a component, and replacing). Or slightly more efficiently (avoids excessive repeated lookups of `d[0]` and indexing of same), `a, b = d[0]`, `d[0] = a + 10, b` – ShadowRanger Apr 04 '18 at 02:30
  • @ShadowRanger Would there be a benefit to keeping this as a tuple? I'm trying to come up with a scenario where that would be useful. – fakedane Apr 04 '18 at 02:35
  • 1
    @fakedane, no problem. I would actually recommend using a numpy matrix to do this. Have an 'n*2' matrix where you can store the x-values in the first column, and the y-values in the second column. Each row represents a different point. – JahKnows Apr 04 '18 at 02:37
  • 1
    @fakedane: The same reasons [you use `tuple`s in general](https://stackoverflow.com/q/626759/364696); preventing in-place modification, reducing memory usage (on 64 bit modern Python, a two-`tuple` adds 64 bytes of overhead, vs. 80 for a len 2 `list`, and the real cost is higher given allocator overhead; the `list` is two allocations, the `tuple` is one), as a mnemonic for a lightweight heterogeneous object rather than a homogeneous sequence, etc. If those benefits don't apply, or mutations are frequent, sure, go w/`list`, but if mutations are rare, the cost of `tuple` replacement is trivial. – ShadowRanger Apr 04 '18 at 02:48