1

I am working on an Autocomplete text editor. It take an input from the user when space is pressed and prints the list of words with prefix mentioned by the user.

Here is the code:

#!/usr/bin/env python

from tkinter import *
import tkinter.font as tkFont


class Node:
    def __init__(self):
        self.word = None
        self.nodes = {}  # dict of nodes

    def __get_all__(self):
        x = []

        for key, node in self.nodes.items():
            if (node.word is not None):
                x.append(node.word)

            x = x + node.__get_all__

        return x

    def __str__(self):
        return self.word

    def __insert__(self, word, string_pos=0):
        current_letter = word[string_pos]

        if current_letter not in self.nodes:
            self.nodes[current_letter] = Node();
        if (string_pos + 1 == len(word)):
            self.nodes[current_letter].word = word
        else:
            self.nodes[current_letter].__insert__(word, string_pos + 1)

            return True

    def __get_all_with_prefix__(self, prefix, string_pos):
        x = []
        #print("We are in the get prefix func", prefix)

        for key, node in self.nodes.items():
            if (string_pos >= len(prefix) or key == prefix[string_pos]):
                if (node.word is not None):
                    x.append(node.word)

                if (node.nodes != {}):
                    if (string_pos + 1 <= len(prefix)):
                        x = x + node.__get_all_with_prefix__(prefix, string_pos + 1)
                    else:
                        x = x + node.__get_all_with_prefix__(prefix, string_pos)

        return x


class Trie:
    def __init__(self):
        self.root = Node()

    def insert(self, word):
        self.root.__insert__(word)

    def get_all(self):
        return self.root.__get_all__

    def get_all_with_prefix(self, prefix, string_pos=0):
        return self.root.__get_all_with_prefix__(prefix, string_pos)


root = Tk()
trie = Trie()
customFont = tkFont.Font(family="arial", size=17)

with open('words_file_for_testing.txt', mode='r') as f:
    for line in f:
        for word in line.split():
            trie.insert(word)


def retrieve_input(self):
    inputValue = content_text.get("1.0", "end-1c")
    print(trie.get_all_with_prefix(inputValue))
    printing_the_list(inputValue)

def printing_the_list(getinputvalue):
    print(getinputvalue)
    print(type(getinputvalue))
    print(trie.get_all_with_prefix("A"))
    print(trie.get_all_with_prefix(getinputvalue))
    #print(type(words))
    #print(words)
    #print(trie.get_all_with_prefix("A"))
    #master = Tk()
    #listbox = Listbox(master)
    #listbox.pack()
    #for item in words:
    # listbox.insert(END, item)

root.title("Autocomplete Word")
root.geometry('800x400+150+200')
content_text = Text(root, wrap='word', font=customFont)
content_text.focus_set()
content_text.pack(expand='yes', fill='both')
scroll_bar = Scrollbar(content_text)
content_text.configure(yscrollcommand=scroll_bar.set)
scroll_bar.config(command=content_text.yview)
scroll_bar.pack(side='right', fill='y')
root.bind("<space>", retrieve_input)
root.mainloop()

Now, I am having problem with its printing_the_list(getinputvalue) function. In this function, getinputvalue is the variable in which user input value is stored. When I manually entered the string to print(trie.get_all_with_prefix("A")) funtion it print the words list as desired but, when I tried to print the prefix list of words with user input value using the getinputvalue variable, got an empty list as [].

The above python code prints:

[]
A 
<class 'str'>
['AAE', 'AAEE', 'AAG', 'AAF', 'AAP', 'AAPSS', 'AAM', 'AAMSI', 'AARC', 'AAII', 'AAO', 'Aar', 'Aaron', 'Aarika', 'Aargau', 'Aaren', 'Aarhus', 'Aara', 'Aarau', 'Aandahl', 'Aani', 'Aaqbiye', 'Aalesund', 'Aalto', 'Aalborg', 'Aalst', 'Aachen', 'A-and-R']
[]

What am I doing wrong.

  • 5
    I'm not helping here, but just know `__insert__` and `__get_all__` are **really bad named methods**. `____` methods are reserved for python built-in, you should never name a method or attribute like this. You can name it like `_` if you want to make it "_private_" (technically not, but it's a convention) – Arount Jul 31 '17 at 16:09
  • agreed, except one minor point, it's more like: `_protected` and `__private` (by convention) – acushner Jul 31 '17 at 16:27
  • 1
    Is the output for your test desirable? When you get all words with prefix `'A'`, you only get back words that begin with two As like `Aaron` and `Aalto`. Is this what you want? – Joe Iddon Jul 31 '17 at 18:13
  • The problem is in `print(trie.get_all_with_prefix(inputValue))` function, it not taking inputValue and returning empty list `[]`. but when I pass string like `print(trie.get_all_with_prefix("A"))` it works perfect. i dont know what is wrong in this line: print(trie.get_all_with_prefix(inputValue)) – Gurjot Singh Mahi Aug 01 '17 at 04:43

1 Answers1

1

Your problem is that when you type A and then press space

inputValue = content_text.get("1.0", "end-1c")

returns 'A ' instead of 'A'.

This is because content_text.get() adds a new line character at the end of the string. To ignore both the newline character and the space, use:

inputValue = content_text.get("1.0", "end-2c")
Josselin
  • 2,593
  • 2
  • 22
  • 35