1

I am using the python csv module and I have a CSV with 3 columns, Item, Part, Category.

I'd like to create a dict that combines all the categories and then sorts their values with the Item:Part.

For Example:

512 SSD SATA,42-000153,Hardware
5M DisplayPort 1.2 Cable,42-000135,Cable
90W AC Adapter,42-000146,Adapter
4 port USB hub,42-000126,Adapter

The result I'm getting is:

mydict = {
    Hardware:{512 SSD SATA:42-000153},
    Cable:{5M DisplayPort 1.2 Cable,42-000135},
    Adapter:{90W AC Adapter:42-000146},
    Adapter:{4 port USB hub:42-000126}
    }

This almost gets me there:

def build_dict(source_file):
    projects = defaultdict(dict)
    headers = ['Product', 'Part Number', 'Category']
    with open(source_file, 'rb') as fp:
        reader = csv.DictReader(fp, fieldnames=headers, dialect='excel',
                                skipinitialspace=True)
        for rowdict in reader:
            if None in rowdict:
                del rowdict[None]
            category = rowdict.pop("Category")
            projects[category] = rowdict
        return dict(projects)

source_file = 'test.csv'

The Result I'm looking for:

mydict = {
    Hardware:{512 SSD SATA:42-000153},
    Cable:{5M DisplayPort 1.2 Cable,42-000135},
    Adapter:{90W AC Adapter:42-000146,4 port USB hub:42-000126}
    }

Please Help!

smac89
  • 39,374
  • 15
  • 132
  • 179
  • 1
    Stackoverflow is a great resource for tech help ,but please do not expect someone to code for you. Please show what you have tried and where you are stuck exactly. – karthikr Jul 24 '15 at 00:32
  • Welcome to StackOverflow. You are obviously using some tool (`csv.DictReader`) that is supposed to read this file into a dict. The title of your question should include the name of this tool and your question should have an output of what you get vs what you expect, then you need to tag your question using the name of the tool. – smac89 Jul 24 '15 at 00:46
  • Sorry, about that, csv.DictReader is built into csv, which is a standard python module. – xbluefishiehatx Jul 24 '15 at 00:50

3 Answers3

3

I'd leverage the use of Python's built-ins to do it:

import csv
from collections import defaultdict

mydict = defaultdict(dict)
with open('inventory.csv', 'rb') as inf:
    for row in csv.DictReader(inf, fieldnames=['Product', 'Part Number', 
                                               'Category']):
        mydict[row['Category']][row['Product']] = row['Part Number']

import json  # for pretty-printing result
print(json.dumps(mydict, indent=4))

Output:

{
    "Hardware": {
        "512 SSD SATA": "42-000153"
    },
    "Adapter": {
        "4 port USB hub": "42-000126",
        "90W AC Adapter": "42-000146"
    },
    "Cable": {
        "5M DisplayPort 1.2 Cable": "42-000135"
    }
}

FWIW, you could also do it this way, which takes a few more lines of code, but would make what's going on in the inner-loop a little more readable. The result would be identical. Note it uses csv.reader not csv.DictReader.

import csv
from collections import defaultdict
from collections import namedtuple

Record = namedtuple('Record', ['product', 'part_number', 'category'])

mydict = defaultdict(dict)
with open('inventory.csv', 'rb') as inf:
    for rec in map(Record._make, csv.reader(inf)):
        mydict[rec.category][rec.product] = rec.part_number  # more readable
martineau
  • 119,623
  • 25
  • 170
  • 301
0

This may work.

import csv
import sys

f = open(sys.argv[1], 'rt')

ret = {}
try:
    reader = csv.reader(f)
    for row in reader:
        ret[row[-1]]={" ".join(row[0:2]):row[-2]}
finally:
    f.close()
print str(ret)
Horacio
  • 2,865
  • 1
  • 14
  • 24
0

Just change the defaultdict to build a list for each item and your code will work again.

def build_dict(source_file):
    projects = defaultdict(list)
    headers = ['Product', 'Part Number', 'Category']
    with open(source_file, 'r') as fp:
        reader = csv.DictReader(fp, fieldnames=headers, dialect='excel',
                                skipinitialspace=True)
        for rowdict in reader:
            if None in rowdict:
                del rowdict[None]
                continue
            category = rowdict.pop("Category")
            projects[category].append(rowdict)
        return dict(projects)

source_file = 'test.csv'

Output:

{'Cable': [{'Part Number': '42-000135', 'Product': '5M DisplayPort 1.2 Cable'}], 'Adapter': [{'Part Number': '42-000146', 'Product': '90W AC Adapter'}, {'Part Number': '42-000126', 'Product': '4 port USB hub'}], 'Hardware': [{'Part Number': '42-000153', 'Product': '512 SSD SATA'}]}

Using json pretty print (thanks martineau)

{
    "Cable": [
        {
            "Part Number": "42-000135",
            "Product": "5M DisplayPort 1.2 Cable"
        }
    ],
    "Adapter": [
        {
            "Part Number": "42-000146",
            "Product": "90W AC Adapter"
        },
        {
            "Part Number": "42-000126",
            "Product": "4 port USB hub"
        }
    ],
    "Hardware": [
        {
            "Part Number": "42-000153",
            "Product": "512 SSD SATA"
        }
    ]
}
smac89
  • 39,374
  • 15
  • 132
  • 179