0

I have a dictionary where item_dictionary[0] corresponds to data[0], and item_dictionary[1] corresponds to data[1].

item_dictionary = {'10350':'cat', '560':'dog'}
names = item_dictionary.values()

data = [[1, 2, 3, 4], [5, 6, 7]]

I tried to write the items in data[0] and data[1] to different .csv files like this:

def writer(item):
    q = data.index(item)    
    myfile = open('%r.csv', 'wb') % names[q]
    wr = csv.writer(myfile)
    wr.writerows(data[q])
    myfile.close()

z = [writer(x) for x in data]

This returns the error:

Traceback (most recent call last):
File "", line 1, in
File "", line 3, in writer
TypeError: unsupported operand type(s) for %: 'file' and 'str'`.

My guess for the 'str' part of the error is that names[q] returns, say, 'cat' instead of cat. However, I don't know what operand type to use instead and don't know how to get around the str problem, so could someone please help me? Thanks.

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • 2
    Warning: in Python, dictionaries are unordered, and the order that the elements show up in `.values()` is arbitrary. So it's not true that "item_dictionary[0] corresponds to data[0], and item_dictionary[1] corresponds to data[1]" -- there *is no* `item_dictionary[0]`. (Try it and see -- you'll get a KeyError.) There's a separate ordered dictionary type, but that's not what you're using. – DSM Nov 04 '12 at 01:48

1 Answers1

3

open('%r.csv', 'wb') % names[q] should be open('%r.csv' % names[q], 'wb').

In the former case you are opening a file named "%r.csv" for writing in binary mode and then attempting to modulo the file object with the contents of names[q]. file objects do not support the modulo operator and so you get the TypeError.

In the latter case we are invoking the format method of the string %r.csv with the module operator resulting in a string that is passed to the open function.


As an aside, you may want to consider another way of associating names to data - you could store names alongside your data in either tuples, dictionaries or class instances:

# Tuples
data = [("cat", [1, 2, 3, 4]), ("dog", [5, 6, 7])]
for name, file_data in data:
    print name, "=>", file_data

# Dictionary (assumes only one instance of name per data point)
data = {"cat": [1, 2, 3, 4], "dog": [5, 6, 7]}
for name, file_data in data.items():
    print name, "=>", file_data

# Class instances (ignore this one if you haven't done any OO before)
# (You don't need it if you don't *know* you need it).
class MyDataType(object):
    def __init__(self, name, data):
        self.name = name
        self.data = data

data = [MyDataType("cat", [1, 2, 3, 4]), MyDataType("dog", [5, 6, 7])]
for data_point in data:
    print data_point.name, "=>", data_point.data
Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • Ok. That fixed one problem only to reveal another flaw in my code. I now get `Traceback (most recent call last): File "", line 1, in File "", line 5, in writer _csv.Error: sequence expected`. –  Nov 04 '12 at 01:51
  • @user1709173 - the csv writer function expects a list *of lists* (or at least an iterable *of iterables* to be passed to it. When it tries to do the following `for row in data: for data_point in row: write_data(data_point)` it finds itself trying to iterate over `int`s and blows up. (`for row in [1, 2, 3, 4]: for data_point in 1: # BOOM! (1 is not iterable)`) – Sean Vieira Nov 04 '12 at 01:59
  • So if `data` is the list of lists, how do I create a csv that contains only one item from `data` instead of both? –  Nov 04 '12 at 02:04
  • Ok. I figured it out. I just made made a zip of `data[q]` and wrote that. –  Nov 04 '12 at 02:17