简体   繁体   中英

dict.setdefault appends one extra (default?) item into the value list

I am using a dictionary to group data from a CSV file, so for instance fist and second columns are the dict key and value will be a list of tuples with column 3,4.

my code snippet is:

import csv
import collections
csvDicData_ = dict()

fh = open('myfile.csv', 'rt')
reader = csv.reader(fh, delimiter=';', skipinitialspace=True)
for indx, row in enumerate(reader):
    if row:
        #-- put in a dictionary form: #csvDicData_[(row[0],row[1])] = (row[2],row[3])
        key   = (row[0],row[1])
        value = (row[2],row[3])
        #-- I'd like to use the row below (commented) insted of the next two, I expect the same result... 
        #csvDicData_.setdefault(key,[value]).append(value)

        if (not key in csvDicData_): csvDicData_[key] = [value]
        else: csvDicData_[key].append(value)

The code above produces the correct result, altough I tried to use csvDicData_.setdefault(key,[value]).append(value) and for some reason that I do not understand, the len(csvDicData_[('field1x','field2x')] )) has always one more item (with value (0,0) that expected.

Why this behaviour (it is like the first line in the CSV file for each key automatically adds the tuple (0,0) to the dictionary/key.

When you do

csvDicData_.setdefault(key,[value]).append(value)

you initialize the list as [value] , if missing, and then append value to it, giving you [value, value] . What you want instead is to initialize with an empty list:

csvDicData_.setdefault(key,[]).append(value)

or use collections.defaultdict(list) and just do

csvDicData_[key].append(value)

The very first time when you do

csvDicData_.setdefault(key,[value]).append(value)

the key will not be there in the dictionary and so the key will be created with the value as [value] . Now, setdefault returns the value corresponding to the key . So, [value] is returned and you are appending value to it. That is why you are always getting one extra element.

This should have been just

csvDicData_.setdefault(key, []).append(value)

now, the empty list will be returned and you will be appending value to it.


Apart from that, you might want to open the file with with statement, like this

with open('myfile.csv', 'rt') as fh:
    reader = csv.reader(fh, delimiter=';', skipinitialspace=True)
    for indx, row in enumerate(reader):
        ....

so that you don't have to worry about explicitly closing the file.

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