0

I have a csv file which contains details of 3 persons name,date of birth,age,sex.blood group, mobile number, phone number. I would like to write those csv details into a nested dict which works when i print d in line 20 but the dict is unordered (i.e) Details of 1st person is in different order when compared to others. I would like to print them as nested dict and also append them to an empty list so that I can get the list by iterating the dict values.

Input:

Name Age Date of birth Sex Blood Group Mobile number Phone number
A     1   01-01-95      M    O +ve      9876543210    01234567
B     2   02-02-99      F    B +ve      9898989898    07854123
C     3   03-03-93      F    A +ve      9123456780    04693218

Here are my codes:

import csv

d={}
ls=[]


def nest():
    with open ("details.csv", 'r') as f:
        reader=csv.DictReader(f)

        for row in reader:

            d.update(row)

            d.update({'Contact Info': {'Mobile Number':d['Mobile Number'],'Phone  Number':d['Phone Number']}})
            d.update({'Personal Details': {'Sex':d['Sex'], 'Blood Group':d['Blood Group'], 'Age':d['Age']}})

            map(d.pop, ['Mobile Number','Phone Number','Sex','Blood Group', 'Age'])

            print d
            ls.append(d)
            print ls

nest()

Output:

[{'Name': 'A','Personal Details': {'Blood Group': 'O +ve', 'Age': '1', 'Sex': 'M'}, 'Contact Info': {'Phone  Number': '01234567', 'Mobile Number': '9876543210'}, 'Date of Birth': '01-01-95'}
 {'Name': 'B','Personal Details': {'Blood Group': 'B +ve', 'Age': '2', 'Sex': 'F'}, 'Contact Info': {'Phone  Number': '07854123', 'Mobile Number': '9898989898'}, 'Date of Birth': '02-02-99'}
 {'Name': 'C','Personal Details': {'Blood Group': 'A +ve', 'Age': '3', 'Sex': 'F'}, 'Contact Info': {'Phone  Number': '04693218', 'Mobile Number': '9123456780'}, 'Date of Birth': '03-03-93'}]
anonymous
  • 131
  • 1
  • 2
  • 13

1 Answers1

1

I think your update logic is a bit twisted, since you are always updating the same dictionary you are actually overriding the previous values you appended to ls.

So if you want to keep your code as is (which I don't recommend) you need to copy the dict before appending it. ls.append(deepcopy(d)) Dicts are mutable types and you always append the same reference to the list, so all elements will have the same value (the last row).

Since you want the keys to be ordered, just use and OrderedDict

I did it in one line just for the golf, but it's roughly how I'd go about it:

def nest(reader):
    return [
        OrderedDict(
            [
                ('Name', row['Name']),
                ('Personal Details',  OrderDicted((k, row[k]) for k in ('Sex', 'Blood Group', 'Age'))),
                ('Contact Info', OrderedDict((k, row[k]) for k in ('Mobile Number', 'Phone Number'))),
                ('Date of Birth', row[k])
            ]
        ) for row in reader
    ]

Edit Also if you are using python 3.6 and your keys are ordered it is just a side effect of the new implementation that should not be relied upon, see this discussion

Community
  • 1
  • 1
Maresh
  • 4,246
  • 18
  • 29
  • My codes doesn't have any problem with update logic. I'm not able to append the dict to a list. When i append the dict, i should get output as items in abc ( as listed above) but im getting it as a,ab,abc as it gets appended everytime – anonymous May 02 '17 at 11:07
  • ls.append(row) provides the desired output format but i need personal info, contact details to be appended too. So when i try, ls,append(d), I don't get the desired output – anonymous May 02 '17 at 11:15
  • I updated my answer, explaining why your code cannot work as is. – Maresh May 02 '17 at 11:33
  • As I said it's really not a nice way, but it's up to you! – Maresh May 02 '17 at 12:38