2

I'm writing a program using dictionaries nested within a list. I want to print the name of each dictionary when looping through the list, but don't know how to do that without calling the entire contents of the dictionary. Here is my code:

sam = {
'food' : 'tortas',
'country' : 'mexico',
'song' : 'Dream On',
}
dave = {
    'food' : 'spaghetti',
    'country' : 'USA',
    'song' : 'Sweet Home Alabama',
    }

people = [sam, dave]

for person in people:
    for key, value in sorted(person.items()):
        print( #person's name +
                "'s favorite " + key + " is " + value + ".")

Here is the output:

's favorite country is mexico.

's favorite food is tortas.

's favorite song is Dream On.

's favorite country is USA.

's favorite food is spaghetti.

's favorite song is Sweet Home Alabama.

Everything works, I just need the names of my dictionaries to print. What's the solution?

  • 2
    Objects don't "have" names in that sense. You can do something like `bob = dave` and then the same object has two names. If you want something like that, add another layer of nesting, making `'dave'` and `'sam'` the keys. – BrenBarn May 17 '16 at 05:55

5 Answers5

3

The (more) correct way of doing this is to construct a dict of dicts instead, such as:

people = {'sam': {'food' : 'tortas',
                  'country' : 'mexico',
                  'song' : 'Dream On',
                  },
          'dave': {'food' : 'spaghetti',
                   'country' : 'USA',
                   'song' : 'Sweet Home Alabama',
                   }
           }

Then you can simply do the following:

for name, person in people.items():
    for key, value in sorted(person.items()):
        print(name + "'s favorite " + key + " is " + value + ".")

This will print the following:

dave's favorite country is USA.
dave's favorite food is spaghetti.
dave's favorite song is Sweet Home Alabama.
sam's favorite country is mexico.
sam's favorite food is tortas.
sam's favorite song is Dream On.

As a side note, it is more readable to use string formatting in your print statement:

print("{0}'s favorite {1} is {2}".format(name, key, value))
Selcuk
  • 57,004
  • 12
  • 102
  • 110
2

what you are basically trying to do is printing the name of a variable. Of course, this is not reccomended. If you really want to do this, you should take a look at this post: How can you print a variable name in python?

What i would do, is to store the name of the dictionary inside of the lists. You could do this by changing 'people = [sam, dave]' to 'people = [["sam", sam], ["dave", dave]]'. This way, person[0] is the name of the person, and person[1] contains the information.

Community
  • 1
  • 1
2

The simplest way is to store the name as a string that maps to the matching variable identifier:

people = {'sam':sam, 'dave':dave}

for name, person in people.items():
    for key, value in sorted(person.items()):
        print(name + "'s favorite " + key + " is " + value + ".")

If you really don't like the idea of typing each name twice, you could 'inline' the dictionaries:

people = {
    'sam':{
        'food' : 'tortas',
        'country' : 'mexico',
        'song' : 'Dream On',
    },
    'dave':{
       'food' : 'spaghetti',
       'country' : 'USA',
       'song' : 'Sweet Home Alabama',
    }
}

Finally, if you can rely on those variables being in the global namespace and are more concerned with just making it work than purity of practice, you can find them this way:

people = ['sam', 'dave']

for name in people:
    person = globals()[name]
    for key, value in sorted(person.items()):
        print(name + "'s favorite " + key + " is " + value + ".")
Sean Gugler
  • 779
  • 8
  • 18
1

Values in a list aren't really variables any more. They aren't referred to by a name in some namespace, but by an integer indicating their offsets from the front of the list (0, 1, ...).

If you want to associate each dict of data with some name, you have to do it explicitly. There are two general options, depending on what's responsible for tracking the name: the collection of people, or each person in the collection.

The first and easiest is the collections.OrderedDict --- unlike the normal dict, it will preserve the order of the people in your list.

from collections import OrderedDict

sam = {
  'food': 'tortas',
  'country': 'Mexico',
  'song': 'Dream On',
  }
dave = {
  'food': 'spaghetti',
  'country': 'USA',
  'song': 'Sweet Home Alabama',
  }
# The OrderedDict stores each person's name.
people = OrderedDict([('Sam', sam), ('Dave', dave)])

for name, data in people.items():
    # Name is a key in the OrderedDict.
    print('Name: ' + name)
    for key, value in sorted(data.items()):
        print('  {0}: {1}'.format(key.title(), value))

Alternatively, you can store each person's name in his or her own dict... assuming you're allowed to change the contents of those dictionaries. (Also, you wouldn't want to add anything to the data dictionary that would require you to change / update the data more than you already do. Since most people change their favorite food or song much more often than they change their name, this is probably safe.)

sam = {
# Each dict has a new key: 'name'.
  'name': 'Sam',
  'food': 'tortas',
  'country': 'Mexico',
  'song': 'Dream On',
  }
dave = {
  'name': 'Dave',
  'food': 'spaghetti',
  'country': 'USA',
  'song': 'Sweet Home Alabama',
  }
people = [sam, dave]

for data in people:
    # Name is a value in the dict.
    print('Name: ' + data['name'])
    for key, value in sorted(data.items()):
        # Have to avoid printing the name again.
        if 'name' != key:
            print('  {0}: {1}'.format(key.title(), value))

Note that how you print the data depends on whether you store the name in the collection (OrderedDict variant), or in each person's dict (list variant).

Kevin J. Chase
  • 3,856
  • 4
  • 21
  • 43
0

Thanks for the great input. This program is for a practice example in "Python Crash Course" by Eric Matthes, so the inefficient "dictionaries inside list" format is intentional. That said, I got a lot out of your comments, and altered my code to get the desired output:

sam = {
    #Added a 'name' key-value pair.
    'name' : 'sam',
    'food' : 'tortas',
    'country' : 'mexico',
    'song' : 'Dream On',
    }
dave = {
    'name' : 'dave',
    'food' : 'spaghetti',
    'country' : 'USA',
    'song' : 'Sweet Home Alabama',
    }

people = [sam, dave]

for person in people:
    for key, value in sorted(person.items()):
        #Added if statement to prevent printing the name.
        if key != 'name':
            print(person['name'].title() + "'s favorite " + key + " is " + value + ".")
    #Added a blank line at the end of each for loop.
    print('\n')

Here is the output:

Sam's favorite country is mexico.
Sam's favorite food is tortas.
Sam's favorite song is Dream On.


Dave's favorite country is USA.
Dave's favorite food is spaghetti.
Dave's favorite song is Sweet Home Alabama.

Thanks again, all who provided insightful answers.