yanir
yanir

Reputation: 13

How to handle CSV with variable columns per row

I've got a file that has a header row with a fixed number of labels and rows of variable length. The last column has a field that should really be a sublist of items, but this list is treated as a continuum of columns.

Example:

Name, Address, Telephone
"Bob Smith", "123 main st", "111-111-1111"
"Jon Smith", "123 main st", "111-111-1111", "222-222-2222"

I ultimately want to iterate over the sublist, in this case telephone #'s.

I've tried using csv dictreader but it drops the extra columns.

Thanks in advance.

Upvotes: 1

Views: 2941

Answers (2)

Mark Tolonen
Mark Tolonen

Reputation: 177481

You don't need DictReader. Use the standard reader and tuple assignment syntax:

Code:

import csv

with open('test.csv') as f:
    r = csv.reader(f)
    next(r) # skip header

    # Note this assigns the 3rd and remaining columns to 'telephone' as a list.
    for name,addr,*telephone in r:
        print(f'name:     {name}')
        print(f'address:  {addr}')
        for i,phone in enumerate(telephone,1):
            print(f'Phone #{i}: {phone}')
        print()

test.csv:

Name,Address,Telephone
"Bob Smith","123 main st","111-111-1111"
"Jon Smith","123 main st","111-111-1111","222-222-2222"

Output:

name:     Bob Smith
address:  123 main st
Phone #1: 111-111-1111

name:     Jon Smith
address:  123 main st
Phone #1: 111-111-1111
Phone #2: 222-222-2222

Upvotes: 3

nosklo
nosklo

Reputation: 222822

As you can see in DictReader docs:

If a row has more fields than fieldnames, the remaining data is put in a list and stored with the fieldname specified by restkey (which defaults to None).

All you must do is pass the restkey parameter and all your extra values will go there.

with open('yourfile.csv') as f:
    cf = csv.DictReader(f, restkey='extra')
    for row in cf:
        print(row)

will print

{"Name": "Bob Smith", "Address": "123 main st", "Telephone": "111-111-1111"}
{"Name": "Jon Smith", "Address": "123 main st", "Telephone": "111-111-1111", "extra": ["222-222-2222"]}

Upvotes: 1

Related Questions