0

I am very novice in python, and I am currently learning the language. I found that array of arrays ( associative arrays ) are called as dictionaries in python ({}) I am facing a problem. I need to build a dictionary and update it in a for loop. My codes are below.

loc = {}
result = { I get the list of records from database here, which has id and status }
for res in result:
    temp={}
    temp['id']= res.id
    temp['status'] = res.status
    loc.update(temp) # this replaces the values every time, i want append

print loc

below is the result expected by me:

loc = { {'id' : 123 , 'status' : 'available' },
        { 'id' : 456 , 'status' : 'unavailable'}
       }

Can someone help me. I tried with :

loc = [] # [] this works with loc.append(temp) 
this gives result as : 
[{'id' : 123 , 'status' : 'available'},{'id' : 456 , 'status' : 'unavailable'}]

But i need the above result with dictionary of dictionaries in python.

MattDMo
  • 100,794
  • 21
  • 241
  • 231
user280960
  • 711
  • 15
  • 30
  • 2
    Your expected result `loc` is not a dict, as it does not contain keys and values. In a dict of dicts, you have keys whose values are dictionaries. What do you intend to use as the keys? Why does `loc` need to be a dict of dicts? A list of dicts, as shown in your bottom result, seems to work fine. – MattDMo Jun 23 '16 at 23:58
  • Dictionary is a key-value pair (indexed by the key). Now what is the key for the outer dictionary? – UltraInstinct Jun 23 '16 at 23:58
  • Why is loc a dictionary? – Jose Romero Jun 23 '16 at 23:59
  • 1
    "Arrays of arrays" is not really a good way to think of a `dict`. A `dict` is a hash table or hash map, with fast look up properties. In Python, the `list` is what's commonly used where you might be use an array in other languages. (There *is* something called an array in Python, but it's rarely used.) – jpmc26 Jun 23 '16 at 23:59
  • 1
    Does every result have a unique `id`? Are `id` and `status` the only fields you are interested in? – ali_m Jun 24 '16 at 00:06
  • @MattDMo Actually, I think maybe it is relevant in a kind of sideways way. The wording the OP used was suggestive of a PHP background, and I think the fact that PHP has "arrays" and "associative arrays" ended up confusing the OP about the nature of the data structures and what data structures are appropriate in Python. – jpmc26 Jun 24 '16 at 00:12
  • @jpmc26 good point. I rolled back to the OP's original text. – MattDMo Jun 24 '16 at 00:15
  • Is your problem solved? If so, please accept an answer; you can write your own if neither of the existing ones are sufficient. If not, then please clarify why the answers didn't solve your problem. – jpmc26 Jun 29 '16 at 00:47
  • Well jpmc26, For me both answers worked, that's why i haven't selected one. – user280960 Jun 29 '16 at 15:06
  • If you are learning Python, you should *not* be investing time in learning Python 2. Those of us who still write it do so because we have to support or migrate legacy code. – BoarGules Jun 05 '21 at 12:18

3 Answers3

2

If id is unique, it seems more likely that what you really want is just a dict mapping id to status.

for res in result:
    loc[res.id] = res.status

If you iterate over loc.viewitems() (in Py3, just loc.items()), you get tuples that pair each id with its status; Python uses tuples as sort of "anonymous lightweight objects", so it works quite similarly to the set of dicts you were trying to build. Used this way, you can look up values by id efficiently (loc[someid] will get you the associated status if the id exists or raise KeyError), while still being able to efficiently iterate them:

for ID, status in loc.viewitems():
    # do stuff with ID and status

A list of dicts makes lookup a O(n) task (where the plain dict is roughly O(1) lookup), and makes iteration a little more ugly, requiring you to use operator.itemgetter to write a similar loop for unpacking, or requiring manual lookup of the both id and status for each item, which is ugly to say the least. It's also much less efficient memory-wise; each two item dict pays fairly substantial memory overhead relative to a single larger dict.

One other option to consider, if you really want this to behave more like JS objects, is using collections.namedtuple. It's sort of dict like; you access attributes with dot syntax, not keys with bracket syntax, but it's much more memory efficient, and it's immutable, so it can go in a set:

from collections import namedtuple

Record = namedtuple('Record', 'id status')

loc = {Record(res.id, res.status) for res in result}

You can then use the namedtuple like a regular tuple (so for ID, status in loc: works), or use named attribute access instead:

for record in loc:
    print(record.id, record.status)
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
1

What you say is your desired output:

loc = {
    {'id' : 123 , 'status' : 'available' },
    {'id' : 456 , 'status' : 'unavailable'}
}

would not be a dict. It would be a set if it worked at all.

But a set can't contain a dict because it's not hashable. A set can only contain hashable elements because it uses the hash for fast lookups. (A hashable item would either be completely immutable or any mutation it experiences would not affect the hash. Note that not affecting the hash implies it also doesn't affect equality. Generally, it's just easier to ensure hashable things are immutable.)

In a dictionary, you must have a key and a value. Your desired output does not describe a key for each inner dict, so a dict isn't the data structure you want. What you probably want is exactly what you found out works:

loc = [
    {'id' : 123 , 'status' : 'available' },
    {'id' : 456 , 'status' : 'unavailable'}
]

This is a list. A list is the go-to data structure for holding a sequence of elements. You can iterate over it:

for i in loc:
    print(i)

or access elements of it via index:

loc[2]

This is probably what you want. There's more you can do with it, like slice it, but I won't get into everything here.

The update function you are calling in your sample code is used for taking each key in the input dict and either adding the key/value pair to it or updating the value for an existing key. You might think of this as "merging" the argument dict into the one before the dot. That's why it overwrote all the values each time; that's how it's supposed to work. Python's documentation is pretty good; you want to get in the habit of consulting it whenever something doesn't behave as you expect.

Community
  • 1
  • 1
jpmc26
  • 28,463
  • 14
  • 94
  • 146
0

You can update a dictionary by adding a new entry or a key-value pair, modifying an existing entry, or deleting an existing entry as shown below in the simple example

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}

dict['Age'] = 8; # update existing entry
dict['School'] = "DPS School"; # Add new entry


print "dict['Age']: ", dict['Age']
print "dict['School']: ", dict['School']

source: iodocs

RckLN
  • 4,272
  • 4
  • 30
  • 34