Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an efficient way of creating a list of tuples using a range?

I'm seeking for an efficient way to combine a number range like (20,24) with another object like {'a': 'b'} to get,

[(20, {'a': 'b'}), (21, {'a': 'b'}), (22, {'a': 'b'}), (23, {'a': 'b'})]

If I had a list of numbers like [20, 21, 22, 23], I know iterating through the list is the way to go. But here I have a range of numbers. So may be there is a way to wrap range elements in tuples more elegantly.

Here is my attempt to achieve this:

min = 20
max = 23
data = {"a": "b"}
result = []
for i in range(min, max + 1):
    result.append((i, data))
print(result)

I just want to know whether there is any better way to do this.

like image 489
nipunasudha Avatar asked Dec 14 '17 10:12

nipunasudha


1 Answers

Indeed, any for loop appending to an empty list can be transformed into a list comprehension.

l = []
for x in range(20, 24):
    l.append((x, data))

Or,

l = [(x, data) for x in range(20, 24)]

However! Note that what you get is this -

for i in l:
     print(id(i[1]))

4835204232
4835204232
4835204232
4835204232

Where the same object being reference-copied multiple times. This is a problem with mutable objects, because if you change one object, they all reflect the change. Because of this, I'd recommend making a copy of your data at each step. You can either use the builtin dict.copy function, or a function from the copy module. In the former case, only a shallow copy is done, so if you have a nested structure, that isn't a good idea.

Anyway, this is how I'd do it -

import copy
l = [(x, copy.deepcopy(data)) for x in range(20, 24)]

If your dictionary isn't complex in structure (for example - {'a' : {'b' : 'c'}}), the dict.copy method that I mentioned above works -

l = [(x, data.copy()) for x in range(20, 24)]
like image 182
cs95 Avatar answered Sep 22 '22 06:09

cs95