When calling a recursive function to order the values, it skips one. How to fix it?

I have a recursive function that reads a list of scout records from a file and then adds them in order of their ID to the list. The function is called with addScouts(1)

. Function below:

def addScouts(self,I):
    i = I
    with open(fileName,"r") as f:
        lines = f.readlines()
        for line in lines:
            if str(line.split(",")[3])[:-1] == str(i):
                self.scoutList.insert(END,line[:-1])
                i += 1
                return self.addScouts(i)
    return

      

My problem is that my file id is ordered 1,2,4,5

since at some point I deleted the scout with id 3. However, when I run the function to re-order the scouts in the list (function above) it only displays the scouts before and including the ID 3. This is because when i = 3

none of the items in the file are equal to 3, so the function reaches the end and returns before it can check the remaining entries.

File contents:

Kris,Rice,17,1
Olly,Fallows,17,2
Olivia,Bird,17,4
Louis,Martin,18,5

      

Any idea how to fix this?

+3


source to share


2 answers


Just select the last column:

 sorted(f,key=lambda x: int(x.split(",")[-1]))

      

You can use bisect to find where to put the new data to keep the ordered data after sorting it once:

from bisect import bisect
import csv
with open("foo.txt") as f:
    r = list(csv.reader(f)) 
    keys = [int(row[-1]) for row in r]
    new = ["foo","bar","12","3"]
    ind = bisect(keys, int(new[-1]))
    r.insert(ind,new)
    print(r)

      

Output:

[['Kris', 'Rice', '17', '1'], ['Olly', 'Fallows', '17', '2'], ['foo', 'bar', '12', '3'], ['Olivia', 'Bird', '17', '4'], ['Louis', 'Martin', '18', '5']]

      

The simplest way to check the first line with a higher id, if none of them above, just add at the end:



import csv
with open("foo.txt") as f:
    r = list(csv.reader(f))
    new = ["foo","bar","12","3"]
    key = int(new[-1])
    ind = None
    for i, row in enumerate(r):
        if int(row[-1]) >= key:
            ind = i
            break
    r.insert(ind, new) if ind is not None else r.append(new)
    print(r)

      

Output:

 [['Kris', 'Rice', '17', '1'], ['Olly', 'Fallows', '17', '2'], ['foo', 'bar', '12', '3'], ['Olivia', 'Bird', '17', '4'], ['Louis', 'Martin', '18', '5']

      

To always add this file in order when adding a new value, we just need to write to a temporary file, write the line to the correct location, and then replace the original with the updated file:

import csv
from tempfile import NamedTemporaryFile
from shutil import move


with open("foo.csv") as f, NamedTemporaryFile(dir=".", delete=False) as temp:
    r = csv.reader(f)
    wr = csv.writer(temp)
    new = ["foo", "bar", "12", "3"]
    key, ind = int(new[-1]), None
    for i, row in enumerate(r):
        if int(row[-1]) >= key:
            wr.writerow(new)
            wr.writerow(row)
            wr.writerows(r)
            break
        wr.writerow(row)
    else:
        wr.writerow(new)
move(temp.name, "foo.csv")

      

foo.csv after the data is in order:

Kris,Rice,17,1
Olly,Fallows,17,2
foo,bar,12,3
Olivia,Bird,17,4
Louis,Martin,18,5

      

+2


source


You can check if your list is the same length as your file, and if not, you run addScouts again, and if true, you end up. Like this:



def addScouts(self,I):
    i = I
    with open(fileName,"r") as f:
        lines = f.readlines()
        for line in lines:
            if str(line.split(",")[3])[:-1] == str(i):
                self.scoutList.insert(END,line[:-1])
                i += 1
                return self.addScouts(i)
    if len(scoutList) < len(lines):
        return self.addScouts(i+1)
    else:
        return

      

+1


source







All Articles