简体   繁体   中英

reading file into dictionary python

This function is meant to read a file into a dictionary, using the birdnames a keys and the weights as values. It is doing what I want but it isnt going through all the lines and im not sure why! Help a girl out? Here is my code:

def bird_weights(filename):
    bird_dict = {}
    f = open(filename, "r")
    for line in f:
        new_line = line.split(":")
        bird_type = new_line[0].capitalize()
        bird_weight = new_line[1].strip().split(' ')
        bw_list = [float(i) for i in bird_weight]
        bird_dict[bird_type] = bw_list
        if bird_type in bird_dict:
            bird_dict[bird_type].extend(bw_list)
        else:
            bird_dict[bird_type] = bw_list

    return bird_dict  

the .txt file is:

bluebird:78.3 89.3 77.0
TANAGER: 111.9 107.65
BlueBird: 69.9
bluebirD: 91.9
tanager: 108.0 110.0

and the code is meant to produce

{"Bluebird":[78.3, 89.3, 77.0, 69.9, 91.9],"Tanager": [111.9, 107.65, 108.0, 110.0]}

what i am getting is:

{"Bluebird":[91.9, 91.9], "Tanager": [108.0, 110.0, 108.0, 110.0] }

I am not sure why

It's because python's dictionary can't have duplicate keys. You are using 'capitalize' method, which made some bird's names identical.

def bird_weights(filename):
    result = collections.defaultdict(list)

    with open(filename, 'r') as f:
        for line in f.readlines():
            bird_name, values = line.strip().split(':')

            # normalization
            bird_name = bird_name.strip().capitalize()
            values = map(lambda v: float(v.strip()), values.strip().split(' '))

            result[bird_name].extend(values)

    return result

Every time you see Bluebird , you're overwriting what was already there. Try something like:

for line in f:
    ...
    if bird_type in bird_dict:
        bird_dict[bird_type].extend(bw_list)
    else:
        bird_dict[bird_type] = bw_list

to add to a pre-existing list for each bird_type .

You cannot have multiple keys of the same value in a Python dict.

You can add an integer to each instance such as:

keys={}
birds={}
with open(file) as f:
    for line in f:
        k,_,v=line.partition(':')
        k=k.capitalize()
        v=map(float, v.split())
        keys[k]=keys.setdefault(k, 0)+1
        birds.setdefault('{} {}'.format(k, keys[k]), []).extend(v)


{'Tanager 1': [111.9, 107.65], 
 'Tanager 2': [108.0, 110.0], 
 'Bluebird 3': [91.9], 
 'Bluebird 2': [69.9], 
 'Bluebird 1': [78.3, 89.3, 77.0]}

Or, use a list of lists kind of structure:

birds={}
with open(file) as f:
    for line in f:
        k,_,v=line.partition(':')
        k=k.capitalize()
        v=map(float, v.split())
        birds.setdefault(k, []).append(v)

{'Bluebird': [[78.3, 89.3, 77.0], [69.9], [91.9]], 
 'Tanager': [[111.9, 107.65], [108.0, 110.0]]}

Or, change append to extend for a flat list:

birds={}
with open(file) as f:
    for line in f:
        k,_,v=line.partition(':')
        k=k.capitalize()
        v=map(float, v.split())
        birds.setdefault(k, []).extend(v)

{'Bluebird': [78.3, 89.3, 77.0, 69.9, 91.9], 'Tanager': [111.9, 107.65, 108.0, 110.0]}

So i know there are already a lot of solutions to this, but i'll just post one more :)

If you want to make your life a little bit easier and don't want to get confused by your code so easily, it sometimes helps to implement not the shortest but the most readable solution. If you're at this time only half understanding what your doing you will have a hard time half a year in the future when trying to change something on this code snippet.

So here is my fairly expressive solution and i think you'll be able to exactly understand what i did when you read through your bird_weights() function:

class Bird(object):
    def __init__(self, name, weights):
        self.name = name
        self.weights = weights

    def __str__(self):
        return self.name + ':' + str(self.weights)

def get_float_list(weights):
    return [float(i.strip()) for i in weights.strip().split(' ')]

def print_birds(birdlist):
    print '{'
    for i in birdlist:
        print str(i) + ','
    print '}'

def bird_weights(f):
    birdlist = []
    for line in f:
        name, weights = line.split(':')
        birdy = Bird(name.capitalize(), get_float_list(weights))
        birdlist.append(birdy)
    print_birds(birdlist)

Happy flapping :)

EDIT: Sorry forgot to mention that you should pass this function now a opened file object (or a list of strings as i did for testing)

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