1

I've made this formula which turns a CSV into a dictionary:

def CSVtoDict(BDF, mode):
    saved={}
    with open('%s%s.csv' % (dataDir,BDF), mode='r') as infile:
        reader = csv.reader(infile)
        for row in reader:
            if mode is 'prune' and row == '':
                break
            else:
                pass
            key = row[0]
            saved[key]=row[1:]
    return saved

I'm trying to make it so that when the mode is 'prune', any string from the CSV such as ['data1', 'data2', '', '', ''] is returned without any ''. But the break statement doesn't seem to work for some reason and things are returned as if there was no if else.

Also do you know what would be the pythonic way of doing this? I feel like this could be more efficient somehow...

Example line from the CSV:

Awareness,ASD,ASD2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

5 Answers5

2

If I understand your question correctly, you're trying to filter out empty rows when mode == 'prune', is that correct? Or are you trying to stop as soon as you hit an empty row (which is what the break would achieve if your conditional was correct)?

The problem is that csv rows are returned as lists, not strings, i.e. a line in a csv file that looks like this:

a,b,1,2

will be returned as ['a','b','1','2'] when iterating through reader. An empty row comes up as [], not ''. If you want to check for an empty row, you can check for len(row) == 0 instead. Also, your else: pass doesn't really do anything so you can leave it out. Result should be something like this:

for row in reader:
    if mode is 'prune' and len(row) == 0:
        break # or continue, if you want to proceed with the rest of the file
    key = row[0]
    saved[key]=row[1:]

If as another answer suggests, you're trying to prune out any row that has an empty field, then change len(row) == 0 to '' in row.

OldGeeksGuide
  • 2,888
  • 13
  • 23
1

I'm thinking you may want to use continue rather than break. Break will take you out of the if/else statement, but continue will take you to the next iteration of the for loop.

Tyler R
  • 474
  • 2
  • 6
  • 15
  • 1
    Break interrupts loops, not if/else blocks. I think you have the right idea, just revise the terminology. – Davy M Jun 09 '17 at 17:49
1

The condition row == '' means the whole row is an empty string. YOu could substitute it with '' in row so:

if mode is 'prune' and '' in row:
user2314737
  • 27,088
  • 20
  • 102
  • 114
1

wait a minute, is that what you want? if you want to remove all the '' if mode == "prune" just do:

def CSVtoDict(BDF, mode):
    with open('%s%s.csv' % (dataDir,BDF), mode='r') as infile:
        reader = csv.reader(infile)
        return [ row for row in reader if row != '' ] if (mode == "prune") else reader
developer_hatch
  • 15,898
  • 3
  • 42
  • 75
1

I think the problem is that you still have to loop through each entry, not just each row. Here is my solution:

# CSV contents
#  'data1', 'data2', 'data3', ''
#  'data4', 'data5', '' ''
#  'data6', '', '', ''

def CSVtoDict(BDF, mode):
    saved={}
    with open('%s%s.csv' % (dataDir,BDF), mode='r') as infile:
        reader = csv.reader(infile)
        for row in reader:
            key = row[0]
            saved[key] = [r for r in row[1:] if not (r is '' and mode is 'prune')]
    return saved


# saved will equal
# {
#   'data1': ['data2', 'data3']
#   'data4': ['data5'], 
#   'data6': [], 
# }
Tom Sitter
  • 1,082
  • 1
  • 10
  • 23