0

I have an array of dictionaries of the form:

[
    {
        generic_key: specific_key,
        generic_value: specific_value
    }
    ...
]

I am trying to interpret this into an array of dictionaries of this form:

[
    {
        specific_key: specific_value
    }
    ...
]

I tried this:

new_array = []
for row in old_array:
    values = list(row.values())
    key = values[0]
    val = values[1]
    new_array.append({key: val})

This works in most cases, but in some, it swaps them around to form a dict like this:

{
    specific_value: specific_key
}

I've looked at the source file, and the rows in which it does this are identical to the rows in which it does not do this.

It's perhaps worth mentioning that the list in question is about 3000 elements in length.

Am I doing something stupid? I guess that maybe list(row.values()) does not necessarily preserve the order, but I don't see why it wouldn't.

EDIT fixed code typo suggesting that it was appending sets

BadRequest
  • 382
  • 1
  • 14
Alex
  • 2,270
  • 3
  • 33
  • 65
  • 3
    `new_array.append({key, val})` is appending a `set` not a `dict`. You need to change the comma to a semi-colon – roganjosh May 20 '19 at 13:17
  • Did you mean to type: `new_array.append({key: val})`. Otherwise the code you have creates a list with some sets in it. – quamrana May 20 '19 at 13:17
  • 2
    Ok, well now you're hitting up against dictionary ordering in older versions of Python. Rather than doing `values()` and then indexing that, why don't you access the values by key in each dict? – roganjosh May 20 '19 at 13:20
  • I'm using python 3.7. – Alex May 20 '19 at 13:20
  • Why the close votes? – Alex May 20 '19 at 13:20
  • You might be using 3.7, but are you sure the data was produced using something that respects order? – roganjosh May 20 '19 at 13:21
  • dictionary doesn't have to keep order - at least in older Pythons. You would have to use `collection.OrderedDict` to keep order or better use `row["generic_key"]` instead of `list()` and `values[0]` – furas May 20 '19 at 13:22
  • I'm not sure that dictionary keep items ordered. Check this post, you may find something interesting: https://stackoverflow.com/questions/39980323/are-dictionaries-ordered-in-python-3-6/39980744. – dome May 20 '19 at 13:22
  • @dome in 3.6 dictionary order is an implementation detail, and guaranteed in 3.7 – roganjosh May 20 '19 at 13:23

1 Answers1

3

The order in which dict keys/values are enumerated is ostensibly arbitrary (there's certainly a logic to it, and as of I think python3.7+, it's consistent, but while I don't know off the top of my head what the ordering criteria are) - if you wanted order, you would have used a list instead of a dict to store them in the first place. If generic_key and generic_value are the same each time, then the ideal way to handle this problem is to simply extract by key:

key = row['generic_key']
value = row['generic_value']

If this isn't the case but there is a consistent way to differentiate between generic_key and generic_value, then you can grab both the keys and values, and do that:

items = tuple(row.items())
if items[0][0] is the generic_key:  # insert whatever condition you need to here
    key = items[0][1]
    value = items[1][1]
else
    key = items[1][1]
    value = items[0][1]
Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
  • Part 2 of this looks like the best way, thank you. I didn't create the original list of dicts myself, and this whole thing is to avoid me having to to manually edit a 3000 element list! – Alex May 20 '19 at 13:26
  • Just a quick note, in Python3.7, items[0][0] doesn't work: TypeError: 'dict_items' object does not support indexing – Alex May 20 '19 at 13:40
  • might need to do `list(row.items())` then, I guess. I forgot that `dict.items()` returns a generator instead of a full list/tuple. – Green Cloak Guy May 20 '19 at 13:41