0

I am trying to add new lines to a list but it seems only the last line is replicated into the list as many times there is a new line generated. So I made a little test script that demonstrates my problem. What I want is to add as many lines to the original list as there are NIGHTS in the line and add a day to the original date, If there are 7 nights I want to have 7 lines only with a different date. From that I generate a text file to mail me, a kind of daily report, so I know what to expect for that day in our B&B and switch hot water boilers on or off

This is my test script in Python

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

from datetime import datetime, timedelta

NIGHTS = 12  # number of nights a guest stays @ our B&B
CHECKIN = 0  # date the guest checks in
aList = []

""" 
contents test agenda.dat
   check in                           nights
     V                                 V
"2016-10-27,1,*,K4,A1,*,D4,*,PD,PF,0,*,7,TEST4,remark"
"2016-10-28,1,*,K4,A1,*,D4,*,PD,PF,0,*,1,TEST1,remark"
"2016-10-29,1,*,K4,A1,*,D4,*,PD,PF,0,*,1,TEST2,remark"
"2016-10-30,1,*,K4,A1,*,D4,*,PD,PF,0,*,2,TEST3,remark"

copy past this into agenda.dat and you have your file

"""

#
# --------- convert date --------- #
def date(cDate=None, format='%Y-%m-%d'):
    if not cDate:
        dDate = datetime.today().date()
    else:
        dDate = datetime.strptime(cDate, '%Y-%m-%d')

    return dDate

#
# --------- get contents agenda -------- #
#
def read_agenda():

    aBooking=[]

    with open("agenda.dat", "r") as f:
        next(f)  # skip header line

        for line in f:
            line = line.strip()
            aBooking.append(line.split(","))

    return aBooking


aList = read_agenda()

# checking out contents of aList
######
for x in aList:
    print x

print "============="
# it checks out

# thought using an empty list would solve the problem, not
bList = []

newline = []  # just declaring everything would help?
n = 0         # not

#######
for x in aList:
    n = int(float(x[NIGHTS]))
    newline = x

    # the first agenda-data line contains '7' so n = 7

    while n > 1:
        cDatum = date(newline[CHECKIN]).date() + timedelta(days=1)
        newline[CHECKIN] = "{:%Y-%m-%d}".format(cDatum)
        newline[NIGHTS] = str(1)

        # just to check if the conversion went ok, yes
        print newline
        # output:
        # ['2016-10-28', '1', '*', 'K4', 'A1', '*', 'D4', '*', 'PD', 
        # 'PF',  '0', '*', '1', 'TEST1', 'remark']

        # and now it happens adding a line to this aray ends in 
        # replicating n lines with the same contents
        # this should not be, a new line should contain a new date
        bList.append(newline)
        n -=1


################
print "==== bList ========="
for y in bList:
    print y
# this prints the same line 7 times!

print "=== aList =========="
for x in aList:
    print x
# and yes the original data is still intact except for the 7 this turned 
# into 1 as desired

question: what do I do wrong here I should get 7 lines with incrementing dates for the first record and 2 lines for the last one.

LMQR15
  • 1
  • 1

1 Answers1

0

Your inner loop while n > 1: keeps modifying the same newline object and appending it to bList. So you don't get 7 different newline objects in bList, you get 7 references to the same newline object.

You can fix this problem by getting rid of that

newline = x

line before while n > 1: and changing the start of the loop to

while n > 1:
    newline = x[:]

That will create a new newline object (copied from x) on each iteration of the loop.

This solution will work if x is a list of strings. However, if x is actually a list of lists, then you may have to create copies of those internal lists, too.

PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
  • Thank you, but that did n't fix it. In stead of 6 x the last date it now copies the first dat 6 times. This is how a friend of mine came with a solution. So inside the loop in stead of newline = x{:} a = [0]*15 # fill with 0's for z in range(0,15): # copy record a[z] = x[z] it is maybe not very Pythonian but it fixed the problem. We where thinking the newline = x copied maybe pointers towards the original record o.s.l.t. – LMQR15 Nov 07 '16 at 08:26
  • Sorry about that, @LMQR15. Obviously, I couldn't test my suggested change because you didn't post a [mcve]. BTW, if `x[z]` is a string or int then `a[z] = x[z]` will work, but it won't if `x[z]` is a list because it does _not_ copy the object, it just makes `a[z]` another name for the same object that `x[z]` names. You may find this article helpful: [Facts and myths about Python names and values](http://nedbatchelder.com/text/names.html), which was written by SO veteran Ned Batchelder. – PM 2Ring Nov 07 '16 at 09:20
  • if you create agenda.dat with the comments on top the example is working, I just tried that to confirm. Thank you for your link and comments, it really helps to understand what went wrong. I am just a beginner but having great fun! – LMQR15 Nov 07 '16 at 10:15