0

I have .csv file, I want to csv convert to dict. Below my code:

testo = []
with open('dTest.csv', 'r') as f:
    reader = csv.DictReader(f)
    for row in reader:
        testo.append(row) 
print testo[4]
teo = json.dumps(testo[4])

My .csv file:

c2:9f:db:67:12:48   c2:9f:db:e7:85:ad   06:27:22:fd:6b:50
      -67                 -51                 -110

But my dictionary results is random:

{u'c2:9f:db:e7:85:ad': u'-51', u'c2:9f:db:67:12:48': u'-67',u'06:27:22:fd:6b:50': u'-110'}

I want my dictionary result is not random:

{u'c2:9f:db:67:12:48': u'-67', u'c2:9f:db:e7:85:ad': u'-51', u'06:27:22:fd:6b:50': u'-110'}
FBillyan
  • 15
  • 5
  • What do you mean random? – Stephen Rauch Jan 25 '17 at 06:00
  • the structure is different from my .csv file @StephenRauch – FBillyan Jan 25 '17 at 06:06
  • 4
    dictionaries are unordered containers. That means that the information stored within a dictionary is not ordered. So you can't ask for `row[2]`, but you can ask for `row['c2:9f:db:67:12:48']`. If you want an ordered container, you're better off with a `list` (`csv.reader` instead of `csv.DictReader`). If you really _really_ want an ordered dictionary, you could try something with `collections.OrderedDict`, but you'd have to put in some effort to read your csv files with such a structure – inspectorG4dget Jan 25 '17 at 06:07
  • 1
    If upgrading your Python version is an option, [Python 3.6's `csv.DictReader` is documented](https://docs.python.org/3.6/library/csv.html#csv.DictReader) as returning instances of `OrderedDict` rather than normal `dict` instances which don't have any particular order. – Blckknght Jan 25 '17 at 06:52

4 Answers4

1

As of Python 3.6, dictionaries will preserve their insertion order: https://mail.python.org/pipermail/python-dev/2016-September/146327.html

A nice "side effect" of compact dict is that the dictionary now preserves the insertion order.

It is a "side effect", however, and not in the official spec so its probably not guaranteed to always work that way in future versions.

user783836
  • 3,099
  • 2
  • 29
  • 34
  • 1
    The docs for the `csv.DictReader` class have actually been updated to say that it returns `OrderedDict` instances, so for this specific situation, relying upon the order is guaranteed to be supported even on implementations of Python where normal dictionaries are still unordered. – Blckknght Jan 25 '17 at 09:15
  • With Python 3.8+ the docs now indicate that a dict is returned - not an OrderedDict -https://docs.python.org/3/library/csv.html Be mindful of this - while this is the accepted answer it is not valid for newer versions of Python – PyNEwbie Mar 07 '21 at 22:51
0

By definition, dictionaries in Python are not ordered, so you cannot maintain (or rely on) any specific ordering of the elements you grab from the CSV file.

Why is python ordering my dictionary like so?

Community
  • 1
  • 1
James
  • 903
  • 7
  • 22
0

There is no way to do what you want. By definition, dictionaries in Python are unordered. As the documentation says,

It is best to think of a dictionary as an unordered set of key: value pairs, with the requirement that the keys are unique (within one dictionary).

Whether the entry is accomplished by reading a file or typing in on the keyboard, Python does not care what order you enter the key-value pairs into the dictionary, as long as each key is unique. The key-value pairs will be stored in arbitrary order.

Why is this? It's because dictionaries are stored in a hash table. The unique key is hashed and the key-value pair is stored at the resultant location. A good enough hash algorithm should be designed for the hash value to be unpredictable. So the desire to keep the dictionary sorted by key all the time is antithetical to the way a dictionary is built.

verbose
  • 7,827
  • 1
  • 25
  • 40
0

If you want to preserver order within a dict you can use OrderedDict:

import csv
from collections import OrderedDict
testo = []
with open('dTest.csv', 'r') as f:
    reader = csv.reader(f)
    headers = next(reader)
    for row in reader:
        testo.append(OrderedDict(zip(headers, row)))

print(testo[0])

this is guaranteed to always have this output:

OrderedDict([('c2:9f:db:67:12:48', '-67'), ('c2:9f:db:e7:85:ad', '-51'), ('06:27:22:fd:6b:50', '-110')])

Other than the order, an OrderedDict has the same properties as a normal Dict so you can e.g. loop over it with for key in test[0]

hansaplast
  • 11,007
  • 2
  • 61
  • 75