zerowords
zerowords

Reputation: 3113

List variable is updating between updates

I have the following definition for a function named intervals. From the print statement at the bottom I get this results (which are half-hour time intervals like 9:00, 9:30, etc expressed as lists in lists, I believe).

[[9, 0], [10, 30], [10, 30], [10, 30]]

I would like the following result.

[[9, 0], [ 9, 30], [10, 0], [10, 30]]

The complete log of the run is as follows. Notice that the list list is only updated once in the while loop between the print "b(efore)" and the print "a(fter)" statements and yet list changes after the after and before the next before. How can that happen?

[9, 30] [[9, 0]] b
[9, 30] [[9, 0], [9, 30]] a
[10, 0] [[9, 0], [10, 0]] b
[10, 0] [[9, 0], [10, 0], [10, 0]] a
[10, 30] [[9, 0], [10, 30], [10, 30]] b
[10, 30] [[9, 0], [10, 30], [10, 30], [10, 30]] a
[[9, 0], [10, 30], [10, 30], [10, 30]]

def intervals(start,end):
    if start>=end:
        return []
    else:
        if 0<=start[1]<30:
            start[1]=0
        else:
            start[1]=30
        list = []
        list.append(start)
        last = start
        new=[0,0]
        while end>last:
            if 30==last[1]:
                new[0]=1+last[0]
                new[1]=0
            else:
                new[0]=last[0]
                new[1]=30
            last=new
            print new,list,"b"
            list.append(new)
            print new,list,"a"
        return list

print intervals([9,0],[10,30])

Can anyone fix it?

Upvotes: 0

Views: 84

Answers (2)

Andrew Clark
Andrew Clark

Reputation: 208565

The reason you see this is that on each iteration of the while loop you append the list new to the end of your list list (which you should really rename, since it masks the built-in list type).

Just move the new=[0,0] line so that it is the first line in the while loop, this will create a new list on each iteration so that your final list won't have several references to the same list:

        ...
        while end>last:
            new=[0,0]
            ...

Note that if you plan on adding any more complexity to this (for example different intervals than 30 minutes), I would really suggest using the datetime module, datetime.timedelta(minutes=30) would probably be useful, for example:

from datetime import datetime, timedelta

def intervals(start, end):
    temp = datetime.min + timedelta(hours=start[0], minutes=start[1])
    last = datetime.min + timedelta(hours=end[0], minutes=end[1])
    interval = timedelta(minutes=30)
    result = []
    while temp <= last:
        result.append([temp.hour, temp.minute])
        temp += interval
    return result

>>> intervals([9, 30], [12, 30])
[[9, 30], [10, 0], [10, 30], [11, 0], [11, 30], [12, 0], [12, 30]]
>>> intervals([9, 45], [12, 15])
[[9, 45], [10, 15], [10, 45], [11, 15], [11, 45], [12, 15]]

Upvotes: 1

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 251096

using while-else loop:

start_hour=9
start_min=30
lis=[[start_hour,start_min]] #simple initialize
stop_hour=12
stop_min=30

while lis[-1][0]!=stop_hour:
    if lis[-1][1]==30:
        lis.append([lis[-1][0]+1,0])
    else:
        lis.append([lis[-1][0],30])
else:
    if lis[-1][1]!=stop_min:
        lis.append([lis[-1][0],stop_min])


print lis        

output:

[[9, 30], [10, 0], [10, 30], [11, 0], [11, 30], [12, 0], [12, 30]]

Upvotes: 0

Related Questions