Home > OS >  Python nested loop using csv and list file
Python nested loop using csv and list file

Time:01-19

I'm using the following code to search for a list of IDs in a particular column of a csv file

#!/usr/bin/python

import csv
import sys

with open(r"C:\Test\inputTest.csv", newline = '') as inputFile:
   inputReader   = csv.reader(inputFile, delimiter=",")
   idFile = open(r"C:\Test\testids.txt")
   loopcounter = 1
   for inputRow in inputReader:
    loopcountr = 1
    print (loopcounter)
    inputString = inputRow[18]
    for id in idFile:
        print ("id: ", id)
        print ("InputString", inputString)
        result = inputString.find(id)
        print (result)

But the nested loop with the id file runs only once, and then doesn't run again.

Output:

1
 id:  123388

InputString  ID
-1
 id:  112233

InputString  ID
-1
 id:  141414
InputString  ID
-1
2
3
4
5
6
7
8
9
10

Any idea why the 2nd loop (the nested loop) doesn't run every time?

CodePudding user response:

Like Tim Roberts mentioned in the comment, "You should read idFile into a list, and then iterate over the list."

You can read the test IDs into a list, like this:

with open("test_ids.txt") as f:
    test_ids = []
    for line in f:
        test_ids.append(line.strip())

Or, if you're comfortable with list comprehensions in Python, this is equivalent:

with open("test_ids.txt") as f:
    test_ids = [x.strip() for x in f.readlines()]

Then, when you're reading the CSV file (presumably) you can compare some data from the CSV against the test IDs.

That could look something like the following. I'm also using enumerate() to count the iterations for me:

with open("input.csv", newline="") as f:
    reader = csv.reader(f)
    next(reader)  # discard header

    for i, row in enumerate(reader, 1):
        input_id = row[0]  # don't use 'id', it's a reserved word
        name = row[1]
        print(f"row #:{i}, input_ID:{input_id}, Name:{name}")

        for test_id in test_ids:
            if test_id == input_id:
                print(f"  {name} matches test_ID {test_id}")

I mocked up this data. The CSV has the ID in the first column, row[0] from the code above:

test_ids.txt
============
105
108

input.csv
=========
ID,Name
105,Alice
106,Bing
107,Che
108,Dee

When I run that code I get:

row #:1, input_ID:105, Name:Alice
  Alice matches test_ID 105
row #:2, input_ID:106, Name:Bing
row #:3, input_ID:107, Name:Che
row #:4, input_ID:108, Name:Dee
  Dee matches test_ID 108

And that's how you can implement a nested loop.

If you're comfortable with doing "lookups" in dictionaries, you can get rid of the nested loop:

with open("test_ids.txt") as f:
    test_ids = {}
    for line in f:
        test_ids[line.strip()] = None

The test_ids dictionary looks like:

{'105': None, '108': None}

And now you simply check if each input ID is "in" that dictionary:

with open("input.csv", newline="") as f:
    ... 
    for i, row in enumerate(reader, 1):
        ...
        if input_id in test_ids:
            print(f"  {name} found in test_IDs")

That produces the similar output:

row #:1, input_ID:105, Name:Alice
  Alice found in test_IDs
row #:2, input_ID:106, Name:Bing
row #:3, input_ID:107, Name:Che
row #:4, input_ID:108, Name:Dee
  Dee found in test_IDs
  • Related