Logan
Logan

Reputation: 31

check existence of data in python dictionary

I have a program that maintains a flat file database of cd information. I am trying to write a function that updates the database. In this function I am checking to see if the artist exists and if so, appending the album name to this artist, but for some reason it will not see that the artist I type in already exists. I made sure that I type it in exactly like it is in the dictionary but for some reason python will not see that it is there. Why would this be happening? I have included sample input as well as the python program. Any help would be greatly appreciated.

import sys

def add(data, block):
    artist = block[0]
    album = block[1]
    songs = block[2:]
    if artist in data:
        data[artist][album] = songs
    else:
        data[artist] = {album: songs}
    return data


def parseData():

    global data
    file='testdata.txt'
    data = {}
    with open(file) as f:
        block = []
        for line in f:
            line = line.strip()
            if line == '':
                data = add(data, block)
                block = []
            else:
                block.append(line)
        data = add(data, block)

    return data

def artistQry():

    global artists, usrChoiceArt, albums, usrChoiceAlb, usrArtist

    artists=sorted(data.keys())
    for i in range(0,len(artists)) :
        print str(i+1) + " : " + artists[i]



    usrChoiceArt = raw_input("Please choose an artist or enter q to quit:")

    if usrChoiceArt=='q' :
        print "Quitting Now"
        exit()
    else :
        albumQry()

def albumQry():

    global artists, usrChoiceArt, albums, usrChoiceAlb, usrArtist

    usrArtist=artists[int(usrChoiceArt)-1]
    albums=sorted(data[usrArtist].keys())

    for i in range(0,len(albums)) :
        print str(i+1) + " : " + albums[i]

    usrChoiceAlb=raw_input("Please choose an album or enter a to go back:")

    if usrChoiceAlb=="a":
        artistQry()
    else:
        trackQry()


def trackQry():

    global artists, usrChoiceArt, albums, usrChoiceAlb, usrArtist

    usrAlbum=albums[int(usrChoiceAlb)-1]
    tracks=data[usrArtist][usrAlbum]

    for i in range(0,len(tracks)) :
        print tracks[i]

    usrChoiceTrack=raw_input("Enter \"a\" to go back or \"q\" to quit:")

    if usrChoiceAlb=="q":
        print "Quitting Now"
        exit()
    elif usrChoiceTrack=="a":
        albumQry()
    else:
        print "Invalid Choice"
        trackQry()


def artistExist(Name):

    for i in range(0,len(data.keys())):

        if Name==data.keys()[i]:
            return True
        else:
            return False




def updData():

    artistName=raw_input("Please enter an artist name:")
    albumName=raw_input("Please enter an album name:")
    trackList=raw_input("Please enter the track list seperated by comma's:")

    if artistExist(artistName):
        data[artistName].append(albumName)
        print data[artistName]
    elif not artistExist(artistName):
        print "Quitting"
        exit()

if __name__ == '__main__':
data = parseData()


if sys.argv[1]=='-l':
    artistQry()
elif sys.argv[1]=='-a':
    updData()

Input data:

Bob Dylan
1966 Blonde on Blonde
-Rainy Day Women #12 & 35
-Pledging My Time
-Visions of Johanna
-One of Us Must Know (Sooner or Later)
-I Want You
-Stuck Inside of Mobile with the Memphis Blues Again
-Leopard-Skin Pill-Box Hat
-Just Like a Woman
-Most Likely You Go Your Way (And I'll Go Mine)
-Temporary Like Achilles
-Absolutely Sweet Marie
-4th Time Around
-Obviously 5 Believers
-Sad Eyed Lady of the Lowlands

Upvotes: 1

Views: 90

Answers (2)

Padraic Cunningham
Padraic Cunningham

Reputation: 180441

Apart from returning too early by returning False in the loop you are doing way too much work, you simply need to use return Name in data:

def artistExist(Name):
    return Name in data # will return True or False with O(1) lookup

Every time you call .keys you are creating a list in python2 so your lookup is actually quadratic in the worst case as opposed to 0(1) with the simple return Name in data. A big part of using a dict is efficient lookups which you lose calling .keys. If you actually wanted to iterate over the keys you would simply for key in data, no call to .keys and no need for range.

Upvotes: 1

chrisaycock
chrisaycock

Reputation: 37930

In your function artistExist, you return False on the very first iteration! Instead, you must wait until all iterations are finished.

for i in range(0,len(data.keys())):

    if Name==data.keys()[i]:
        return True
return False

In addition to what Padraic Cunningham says below, the elif here is also redundant:

if artistExist(artistName):
    ...
elif not artistExist(artistName):
    ...

If something isn't True, then it can only be False. So really you should just have

if artistExist(artistName):
    ...
else:
    ...

And since the function is just a needless one-liner, an even better expression is

if artistName in data:
    ...
else:
    ...

Upvotes: 1

Related Questions