Home > Blockchain >  Issue with printing correct row based on match
Issue with printing correct row based on match

Time:04-14

I'm using a function to iterate through rows of a csv (data_file) and it is intended to print the row which matches. The issue I'm seeing is that it always prints the last row from the csv instead of the matched row.

def read_ability(data_file, ability):
    with open(data_file, 'r ') as f:
        reader = csv.reader(f, delimiter=',')
        for i in reader:
            if i[0] == ability:
                printout = tk.Label(output, text=i, wraplength=500, justify=tk.LEFT)
                printout.pack()

The same principle used in a terminal window

def read_ability(data_file, ability):
    with open(data_file, 'r ') as f:
        reader = csv.reader(f, delimiter=',')
        for i in reader:
            if i[0] == ability:
                print(i)

prints only the intended row.

I'm interpreting this result as the tkinter attempt overwriting with every row because there was a match instead of just the match. Though, I'm unsure how to correct this.

I tried putting a break statement after the pack statement to see if it would stop after the match. It made no difference.

Adding the code that is passing the arguments as initial response indicated code was functional.

def open_file(data_file):
    with open(data_file, 'r ') as f:
        reader = csv.reader(f, delimiter=",")
        next(reader)
        r = 0
        c = 0
        for widget in results.winfo_children():
            widget.destroy()
        for i in reader:
            button = tk.Button(results, text=i[0], relief=tk.RIDGE, command=lambda: read_ability(data_file, i[0]))
            button.grid(row=r, column=c)
            c  = 1
            if c == 10:
                r  = 1
                c = 0

CodePudding user response:

It all came down to how you call the function in command. The reason it kept returning the last ability because that was the last item in the loop so that was the value that got assigned to the command

Namely, if u is the ability then you pass the value of the button the function like this:

Button(results, text=u, relief=RIDGE,command= lambda u=u: match_values(u))

Below, I cleaned up your code a bit by separating the above into functions so that it is easier to read and follow;

This function loads the file and puts it into a list of tuples where each tuple is a row. This way you don't have to re-read the file

def load_data(data_file):
    uniq_vals = []

    # close off file connection before doing further stuff
    with open(data_file, 'r ') as f:
        # load file
        reader = csv.reader(f, delimiter=",")

        # convert csv to set of tuples (separate value for each column so if you have more columns, add more tuples)
        datalist = [(rows[0],rows[1]) for rows in reader]
    return(datalist)

This function is used to find the rows in the csv file that correspond to ability (=u)

def match_values(u):
    collection=[] # initiate container

    iterate each row and collect those that match ability
    for row in datalist:
        if u==row[0]:
            collection.append(row)

    # this just prints the above into a table
    ncols = len(collection[0]) # get number of columns
    nrows = len(collection) # get number of rows
    
    output = Tk()
    rows = []
    for i in range(nrows):
        #grid with a row offset (looks prettier I think)
        Label(output,text=collection[i][0]).grid(row=1 i,column=0)
        Label(output,text=collection[i][1]).grid(row=1 i,column=1)

This function ultimately executes by printing the unique ability in a grid when you press the button, it returns the rows that match that ability.

def make_options(datalist):
    # initiate list to save unique values
    uniq_vals = [

    # get unique ability values
    uniq_vals = set(list(zip(*datalist))[1])
    
    # initate option window
    results = Tk()
    r=0
    c=0
    offset = 0

    # make grid of buttons for each unique ability
    for u in uniq_vals:
        print(u) # for our reference
        # make button
        button = Button(results, text=u, relief=RIDGE,command= lambda u=u: match_values(u))
        button.grid(row=r, column=c)
        
        c  = 1
        if c == 10:
            r  = 1
            c = 0
 
# call the functions:   
datalist = load_data(data_file)
make_options(datalist)

Cleaning Up

Currently, the above does not close existing windows so probably want to handle that.

  • Related