Ravash Jalil
Ravash Jalil

Reputation: 820

Condensing Repetitive Code

I created a simple application that loads up multiple csv's and stores them into lists.

import csv
import collections

list1=[]
list2=[]
list3=[]


l = open("file1.csv")
n = open("file2.csv")
m = open("file3.csv")

csv_l = csv.reader(l)
csv_n = csv.reader(n)
csv_p = csv.reader(m)

for row in csv_l:
    list1.append(row)

for row in csv_n:
    list2.append(row)

for row in csv_p:
    list3.append(row)

l.close()
n.close()
m.close()

I wanted to create a function that would be responsible for this, so that I could avoid being repetitive and to clean up the code so I was thinking something like this.

def read(filename):
    x = open(filename)
    y = csv.reader(x)
    for row in y:
        list1.append(row)
    x.close()

However it gets tough for me when I get to the for loop which appends to the list. This would work to append to 1 list, however if i pass another file name into the function it will append to the same list. Not sure the best way to go about this.

Upvotes: 2

Views: 117

Answers (3)

Dogweather
Dogweather

Reputation: 16779

I like @DNA's approach. But consider a purely functional style. This can be framed as a map operation which converts

["file1.csv", "file2.csv", "file3.csv"]

to...

[list_of_rows, list_of_rows, list_of_rows]

This function would be invoked like this:

l, n, m = map_to_csv(["file1.csv", "file2.csv", "file3.csv"])

And map_to_csv could be implemented something like this:

def map_to_csv(filenames):
    return [list(csv.reader(open(filename))) for filename in filenames]

The functional solution is shorter and doesn't need temporary variables.

Upvotes: 0

DNA
DNA

Reputation: 42597

You just need to create a new list each time, and return it from your function:

def read(filename):
    rows = []
    x = open(filename)
    y = csv.reader(x)
    for row in y:
        rows.append(row)
    x.close()
    return rows

Then call it as follows

list1 = read("file1.csv")

Another option is to pass the list in as an argument to your function - then you can choose whether to create a new list each time, or append multiple CSVs to the same list:

def read(filename, rows):
    x = open(filename)
    y = csv.reader(x)
    for row in y:
        rows.append(row)
    x.close()
    return rows

# One list per file:
list1 = []
read("file1.csv", list1)

# Multiple files combined into one list:
listCombined = []
read("file2.csv", listCombined)
read("file3.csv", listCombined)

I have used your original code in my answer, but see also Malik Brahimi's answer for a better way to write the function body itself using with and list(), and DogWeather's comments - there are lots of different choices here!

Upvotes: 3

Malik Brahimi
Malik Brahimi

Reputation: 16711

You can make a single function, but use a with statement to condense even further:

def parse_csv(path):
    with open(path) as csv_file:
        return list(csv.reader(csv_file))

Upvotes: 3

Related Questions