0

I'm new to python and programming. Im starting by seeing videos and reading books but I'm also doing a project and I'm stuck. So I have a list

list_ot = [123, 234, 774, 539, 492, 556]

And I have a csv file like this:

Sin, ot, cant
1, 123, 999
12, 234, 888
23, 123, 768
22, 774, 442

After opening the csv file, I want to make a for loop to create lists named after the items in the first list to save some rows in them according to an if statement. Something like this,

Reader = CSV.dictreader(file)

for i in list_ot:
    for row in reader:
        if I == row['ot']:
            (List_named_i).append(row)

Please help me :)

Prasad
  • 5,946
  • 3
  • 30
  • 36
Juan41
  • 25
  • 6
  • Trust me, you really _don't_ want to create `List_named_i` in a loop like that. You can put your lists into a list, and access them by index number. Or if you want to be able to identify them by name you can put them into a dict, with the name as the dict key. – PM 2Ring Oct 14 '17 at 07:12
  • For further info on this important topic please see [How do I create a variable number of variables?](https://stackoverflow.com/questions/1373164/how-do-i-create-a-variable-number-of-variables) and [Why you don't want to dynamically create variables](http://stupidpythonideas.blogspot.com.au/2013/05/why-you-dont-want-to-dynamically-create.html). – PM 2Ring Oct 14 '17 at 07:15
  • 1
    Firstly, Stackoverflow isn't here to write code, it's to help you understand why your code is broken. Secondly, this is a complete hack and any proficient Python programmer would look for the correct way to do it instead i.e. by using dictionaries. – Vasili Syrakis Oct 14 '17 at 07:20
  • 1
    and as you're a beginner, look at python dictionaries (the data type, not books) which should help you for your question – 576i Oct 14 '17 at 07:21
  • 1
    @VasiliSyrakis Hey, at least Juan posted some code! Sure, it has some problems, but we all have to start somewhere. – PM 2Ring Oct 14 '17 at 07:22
  • But, yes, there are various problems with that code. Python key words like `for` and `if` must be written in lowercase. You should change your code so that it actually runs. Also, looping over the reader inside another loop like that won't do what you want: it'll read through the file fine the first time, but on the following loops there'll be nothing left to read. – PM 2Ring Oct 14 '17 at 07:25
  • FWIW, even though I posted those links I _didn't_ close this question as a dupe myself, because there are other issues with the code apart from the "variable variables", and the incorrect cases of various words. IMHO, those issues are secondary to the code's incoherent loop structure. – PM 2Ring Oct 14 '17 at 07:45
  • Ok, I'll look into the answers and dictionarys. Please don't take in consideration the upper cases problems, i put them accidentally because I'm using my phone. I'll be more careful next time. Thanks for all the answers – Juan41 Oct 14 '17 at 15:35
  • I don't really get why it is a bad idea to create a list named I in a loop like I wanted to do in the first fime – Juan41 Oct 14 '17 at 15:39
  • @Juan41 Did you read the material I linked earlier? The info at the Stack Overflow page I liked may be a little confusing, so it may be better to start with the second link, http://stupidpythonideas.blogspot.com.au/2013/05/why-you-dont-want-to-dynamically-create.html – PM 2Ring Oct 15 '17 at 07:51
  • @PM2Ring sorry I didn't see the comment. I will check on that. Thank you so much! – Juan41 Oct 15 '17 at 15:21

2 Answers2

1

As mentioned in the comments, it's not a good idea to dynamically create list names in a loop. Instead, you should use a collection like a list or dictionary to save your lists. I'll show how to do that below.

I also mentioned that doing this sort of thing won't work:

for i in list_ot:
    for row in reader:

On the first run of the outer for i in list_ot: loop we read through the whole file in the inner for row in reader: loop. And then when we get to the second run of the list_ot loop the file cursor will still be at the end of the file, so there will be no data left to read, and the inner loop will finish immediately. We could reset the file cursor to the start of the file, using the file's .seek method, but it's better to avoid re-reading the same file data multiple times.

Instead, when we read a row, we need to check if its 'ot' field matches one of the values in list_ot, and if it does we can save the row into the appropriate list.

The code below shows how to save your data into a dictionary of lists. Please study it carefully! This code was designed to run on Python 3, but it should also run correctly on Python 2 (although strictly speaking you should open the CSV file in binary mode in Python 2).

The csv.DictReader yields an OrderedDict of each row that it reads. This can be handy if you need to preserve the order of the fields in the row, but if you don't need to preserve the order then you can easily convert the OrderedDict to a plain dict, which is what m code does when it saves a row into the mylists dictionary.

import csv

list_ot = [123, 234, 774, 539, 492, 556]

# Create a dict of empty lists, with the numbers in list_ot as the keys
mylists = {k: [] for k in list_ot}

with open('data', 'r') as f:
    reader = csv.DictReader(f, skipinitialspace=True)
    for row in reader:
        print(row)
        ot = int(row['ot'])
        if ot in mylists:
            mylists[ot].append(dict(row))
print()

for k in list_ot:
    print(k, mylists[k])

output

OrderedDict([('Sin', '1'), ('ot', '123'), ('cant', '999')])
OrderedDict([('Sin', '12'), ('ot', '234'), ('cant', '888')])
OrderedDict([('Sin', '23'), ('ot', '123'), ('cant', '768')])
OrderedDict([('Sin', '22'), ('ot', '774'), ('cant', '442')])

123 [{'Sin': '1', 'ot': '123', 'cant': '999'}, {'Sin': '23', 'ot': '123', 'cant': '768'}]
234 [{'Sin': '12', 'ot': '234', 'cant': '888'}]
774 [{'Sin': '22', 'ot': '774', 'cant': '442'}]
539 []
492 []
556 []
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
0

Another simpler alternative for this would be to make use of Pandas. Consider this code:

example.csv:

Sin,ot,cant
1, 123, 999
12, 234, 888
23, 123, 768
22, 774, 442

Code:

import pandas as pd
list_ot = [123, 774, 539, 492, 556]  # Removed 234 from your list for verification
df_csv = pd.read_csv('example.csv')
list_named_i = df_csv[df_csv.ot.isin(list_ot)]
print(list_named_i)

Output:

   Sin   ot  cant
0    1  123   999
2   23  123   768
3   22  774   442
Prasad
  • 5,946
  • 3
  • 30
  • 36