简体   繁体   中英

Appending to a list but list only returns last value

I have a spreadsheet of values for subway lines and their stops. Basically, I am trying to iterate over the CSV file so that when you input a train line it spits out all the stops. I am doing this by creating a dictionary where the key is the train line and the values are a list of the stops. I am telling the function to append but when I print it only shows the last value on the sheet. Thanks for your help!

import os;
class MTALines:
    def __init__(self,train="",stop_name=""):
        self.__points=[];
        self.train=train;
        self.stop_name=stop_name;
    def addLine(self,stop_name):
        self.__points.append(self.stop_name);
    def __repr__(self):
        string=""
        for item in self.__points:
            string+=item+","
        return string

def main():
    inFile = open("hw8 - mta train stop data.csv", "r")
    header = inFile.readline();

    MTA={};
    for line in inFile:
        parts = line.split(',');
        stop_id=parts[0]
        train=stop_id[0]
        stop_name=parts[2]
        getstops = MTALines(train,stop_name);
        getstops.addLine(stop_name);
        MTA[train] = getstops;        


    trainline=""
    while trainline!="done":
        trainline=input("Please enter a train line, or 'done' to stop: ")
        print(trainline,"line:",MTA[trainline])


main();

Update:

As requested here are a few lines of the CSV file:

stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,zone_id,stop_url,location_type,parent_station
101,,Van Cortlandt Park - 242 St,,40.889248,-73.898583,,,1,
101N,,Van Cortlandt Park - 242 St,,40.889248,-73.898583,,,0,101
101S,,Van Cortlandt Park - 242 St,,40.889248,-73.898583,,,0,101
209S,,Burke Av,,40.871356,-73.867164,,,0,209
210,,Allerton Av,,40.865462,-73.867352,,,1,
210N,,Allerton Av,,40.865462,-73.867352,,,0,210
210S,,Allerton Av,,40.865462,-73.867352,,,0,210

I think you're making this task a little more complicated than it needs to be. You don't really need a custom MTALines class, you can store the data for each stop in a dict, each line can be a list of those dicts, and each line list can live in the MTA dict. It's convenient to use a defaultdict for MTA, as that will automatically create new lists as needed.

Also, there's no need to parse the CSV file data by hand, there's a csv module for that. And by using its DictReader class we can get it to read the data into a dict. It actually uses OrderedDict, to preserve the order of the fields.

Here's my version of your code. I changed the name of the CSV file because I hate filenames with spaces in them. ;) Because we're using a defaultdict of lists for MTA if we try to look up a non-existent line we get an empty list.

import csv
from collections import defaultdict

def main():
    MTA = defaultdict(list)
    with open("train_data.csv", "r") as inFile:
        reader = csv.DictReader(inFile)
        #print(reader.fieldnames)
        for row in reader:
            # Get the line id from the stop id
            train = row['stop_id'][0]
            # Extract the desired fields to a new dict
            data = {'stop_id': row['stop_id'], 'stop_name': row['stop_name']}
            MTA[train].append(data)

    while True:
        line_id = input("Please enter a train line, or 'done' to stop: ")
        if line_id == "done":
            break
        print("line:", line_id)
        for stop in MTA[line_id]:
            print(stop['stop_id'], stop['stop_name'])

main()

demo output

Please enter a train line, or 'done' to stop: 1
line: 1
101 Van Cortlandt Park - 242 St
101N Van Cortlandt Park - 242 St
101S Van Cortlandt Park - 242 St
Please enter a train line, or 'done' to stop: 2
line: 2
209S Burke Av
210 Allerton Av
210N Allerton Av
210S Allerton Av
Please enter a train line, or 'done' to stop: 3
line: 3
Please enter a train line, or 'done' to stop: done

I think you may need a defaultdict to collect lists of MTALines instances.

It looks like your dict MTA may overwrite entries if the same train occurs multiple times.

Try this:

from collections import defaultdict

...

def main():
    inFile = open("hw8 - mta train stop data.csv", "r")
    header = inFile.readline()

    MTA = defaultdict(list)  # create defaultdict here
    for line in inFile:
        parts = line.split(',')
        stop_id = parts[0]
        train = stop_id[0]
        stop_name = parts[2]
        getstops = MTALines(train,stop_name)
        getstops.addLine(stop_name)
        MTA[train].append(getstops)   # append to list of MTALines 
    ...

Now the 'problem' might be how to format an entry from the MTA collection:

print(trainline, "line:", MTA[trainline])

Your problem is that you made __points as an instance variable. It will only be available for the instance. Obviously you will get the last stop or last instance value. For a quick fix, use __points as class variable like below.

class MTALines:
    __points=[];
    def __init__(self,train="",stop_name=""):
        self.train=train;
        self.stop_name=stop_name;
    def addLine(self,stop_name):
        MTALines.__points.append(self.stop_name);
    def __repr__(self):
        string=""
        for item in self.__points:
            string+=item+","
        return string

At the end you can use your list as MTALines.__points

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM