Python Forum
Writing a Linear Search algorithm - malformed string representation
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Writing a Linear Search algorithm - malformed string representation
#1
I am writing a linear search algorithm. I've got the main logic under my belt but it's the string representation that I haven't got right. Below is my script and output in my REPL. When I try to search (I call the method seek) for an integer within a list of intergers, the item I test is clearly present but my output shows: "False" as if it is not present.

What can you people tell me about what is wrong with my __str__ and what might you people recommend I use instead? Thanks.

Code:

class LinearSearch:
    # This class accepts an array and an item
    def __init__(self, entered_list=None, item=None):
        self.entered_list = entered_list
        self.item = item
        
    def seek(self, item):
      # Loop through the array and check if the current array element is equal to the item
      for index in self.entered_list:
        if index == item:
            # If it is True, return the index at which the element is found
            return index
        # If the item is never found, return -1
        return False
    
    def __str__(self):
        result = self.seek(self.item)
        if result:
            return str(result) 
        else:
            return "Not Present"
Here is the REPL inputs and outputs:

$ python
Python 3.11.6 (main, Nov 14 2023, 09:36:21) [GCC 13.2.1 20230801] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from linear import LinearSearch
>>> list_obj = [1,2,4,5,7,12,256]
>>> item = 7
>>> item_exists = LinearSearch(list_obj,item)
>>> item_exists
<linear.LinearSearch object at 0x7ff5338add50>
>>> item_exists.seek(7)
False
>>> item_exists.seek(256)
False
>>>
Reply
#2
(Jan-08-2024, 01:28 PM)Drone4four Wrote: I am writing a linear search algorithm. I've got the main logic under my belt but it's the string representation that I haven't got right. Below is my script and output in my REPL. When I try to search (I call the method seek) for an integer within a list of intergers, the item I test is clearly present but my output shows: "False" as if it is not present.

What can you people tell me about what is wrong with my __str__ and what might you people recommend I use instead? Thanks.

Code:

class LinearSearch:
    # This class accepts an array and an item
    def __init__(self, entered_list=None, item=None):
        self.entered_list = entered_list
        self.item = item
        
    def seek(self, item):
      # Loop through the array and check if the current array element is equal to the item
      for index in self.entered_list:
        if index == item:
            # If it is True, return the index at which the element is found
            return index
        # If the item is never found, return -1
        return False
    
    def __str__(self):
        result = self.seek(self.item)
        if result:
            return str(result) 
        else:
            return "Not Present"
Here is the REPL inputs and outputs:

$ python
Python 3.11.6 (main, Nov 14 2023, 09:36:21) [GCC 13.2.1 20230801] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from linear import LinearSearch
>>> list_obj = [1,2,4,5,7,12,256]
>>> item = 7
>>> item_exists = LinearSearch(list_obj,item)
>>> item_exists
<linear.LinearSearch object at 0x7ff5338add50>
>>> item_exists.seek(7)
False
>>> item_exists.seek(256)
False
>>>

Ensure that your __str__ method in the list class returns the actual content of the list, not a boolean value. Use return str(self.items) to display the list correctly. If you are still facing the issue you should review your linear search algorithm's logic.
Reply
#3
Hi @EdwardMatthew. Thank you for your reply! You said:
(Jan-08-2024, 01:55 PM)EdwardMatthew Wrote: If you are still facing the issue you should review your linear search algorithm's logic.

I identified the issue with my logic that you might have been referring to. Originally the second return statement within the for loop was the problem. I reduced it by four spaces and now the input/outputs are improved. Here is my latest script:

class LinearSearch:
    # This class accepts an array and an item
    def __init__(self, entered_list=None, item=None):
        self.entered_list = entered_list
        self.item = item
        
    def seek(self, item):
    # Loop through the array and check if the current array element is equal to the item
        for index in self.entered_list:
            if index == item:
                # If it is True, return the index at which the element is found
                return index
            # If the item is never found, return -1
        return False
Here is my REPL:

>>> from linear import LinearSearch
>>> list_obj = [1,2,4,5,7,12,256]
>>> item = 7
>>> item_exists = LinearSearch(list_obj,item)
>>> item_exists.seek(256)
256
>>> item_exists.seek(2561)
False
>>> 
So it works a little better now. When an item is not found, it returns False. But when the item is found, the item is printed. The problem now is that in reality I intend to return the index value. As far as I can tell, the for loop should be returning the index, not the item. Any further feedback on how to resolve this next issue is welcome.

Quote:Ensure that your __str__ method in the list class returns the actual content of the list, not a boolean value. Use return str(self.items) to display the list correctly.
Thank you for this lead. I have a general sense of what you mean - - I understand where you've pointed out that in my __str__ representation I was testing for a bool. I get that. You are right that I don't really want to test whether it is True or False. But I am not trying to show or return the list of items either as you may have also suggested; rather, just the specific single index position and only if it is present in the entered list.

For now I've commented out the __str__ but the new issue above where I am returning the item value instead of the index value remains.
Reply
#4
What is the purpose of this class? Use in to find out if an object is in an iterable, or list.index() to find out where an object is in an indexable. Currently, seek doesn't appear to know what it wants to do. Either seek should return the location of the value (or -1 if not found), or it should return True/False. It makes no sense to return the value or -1. What happens if -1 is the value you are seeking?
Reply
#5
Hi @deanhystad, Thank you for your feedback.

(Jan-08-2024, 03:28 PM)deanhystad Wrote: What is the purpose of this class? Use in to find out if an object is in an iterable, or list.index() to find out where an object is in an indexable. Currently, seek doesn't appear to know what it wants to do. Either seek should return the location of the value (or -1 if not found), or it should return True/False. It makes no sense to return the value or -1. What happens if -1 is the value you are seeking?

To address your comment about returning -1, that is a misnomer and not relevant to my Python script. The reason why you see -1 is that I am taking a course on Udemy teaching algorithmic software design, but it's in JavaScript. My task is to take the pseudo code provided in the course but implement in the algorithm in Python. Then I compare my Python solution to his JavaScript solution afterwards. My understanding is that in JavaScript the convention is to return -1 in contexts where there is a None or null value (or something like that when a value is not found). For my purposes in Python, the correct intended result is to return False like I have it. What I am trying to say is that it is safe to ignore the return -1 annotation as it is actually not relevant here. I apologize for the miscommunication. I have corrected it in my script so that when I share my code snippet in the future, it won't cause as much confusion.

To answer your first question, the purpose of the class is to complete a linear search by locating the index if the item is present. Else, return False. I think I might see your point about how __str__ should indicate the purpose of the class. In its current form, I gather my script doesn't really do that very well. At this point I am not entirely sure how I'd go about improving this exactly. Would it be better to indent the __str__ representation method so that it is positioned within the def seek(self) class method? I don't think this is what you are suggesting, just a last ditch question on my part since at this point I am grappling at straws.
Reply
#6
Eureka! I got it working. Using enumerate is the technique I need. This filled the gap.

Here is my latest script:

class LinearSearch:
    # This class accepts a list as input
    def __init__(self, entered_list=None): 
        self.entered_list = entered_list
                
    def seek(self, item):
        # Loop through the list and check if the current element is equal to the item
        for index, value in enumerate(self.entered_list):
            if value == item:
            # If value found, return the index 
                return index
        # If the item is never found, return False
        return False

    def __str__(self):
        result = self.seek(self.index)
        if result:
            return str(result) 
        else:
            return "Not Present"
Here is me testing my script in my REPL:

› python
Python 3.11.6 (main, Nov 14 2023, 09:36:21) [GCC 13.2.1 20230801] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from linear import LinearSearch
>>> list_obj = [1,2,4,5,7,12,256]
>>> item_exists = LinearSearch(list_obj)
>>> item_exists.seek(256)
6
>>> item_exists.seek(1)
0
>>> item_exists.seek(100000)
False
>>>
As you can see, now the index values are successfully being returned when found but when an item is not present, returns False.

I am much closer to where I want to be.

The only thing left over is to write a proper string representation method.
Reply
#7
This is a bad design:
    def seek(self, item):
        # Loop through the list and check if the current element is equal to the item
        for index, value in enumerate(self.entered_list):
            if value == item:
            # If value found, return the index 
                return index
        # If the item is never found, return False
        return False
Try list_obj = [0, 1, 2, 3, 4] and item = 0
Reply
#8
(Jan-08-2024, 04:39 PM)deanhystad Wrote: This is a bad design:
    def seek(self, item):
        # Loop through the list and check if the current element is equal to the item
        for index, value in enumerate(self.entered_list):
            if value == item:
            # If value found, return the index 
                return index
        # If the item is never found, return False
        return False
Try list_obj = [0, 1, 2, 3, 4] and item = 0

this works fine, though? Are you trying to point to a falsiness side effect? It would be a problem potentially if you used it as "if seek(item)", but I am not sure if he will use it like that...
Reply
#9
(Jan-08-2024, 04:39 PM)deanhystad Wrote: Try list_obj = [0, 1, 2, 3, 4] and item = 0

It seems to run for me as expected:

Quote:$ python
Python 3.11.6 (main, Nov 14 2023, 09:36:21) [GCC 13.2.1 20230801] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from linear import LinearSearch
>>> list_obj = [0,1,2,3,4,5]
>>> item_exists = LinearSearch(list_obj)
>>> item_exists.seek(0)
0
Reply
#10
__str__() doesn't work at all anymore. Call it and you get an Attribute error.

I also think that seek() doesn't work. seek() returns the index of the value in the list, or False if not found. When I see that a function returns False, I think that I can treat the return value as a bool. This does not work for seek().
x = LinearSearch([1, 2, 3])
if (index := x.seek(1)):
    print(1, "found at", index)
else:
    print(1, "is not in list")
Output:
1 is not in list
1 is found at index==0. When I use the .seek() return value as a bool, 0 is treated the same as False. The method works if the value not in the list, or if it is anywhere except the front of the list.

I rewrite my code like this to make it work:
x = LinearSearch([1, 2, 3])
if (index := x.seek(1)) != False:
    print(1, "found at", index)
else:
    print(1, "is not in list")
Output:
1 is not in list
Oops! That doesn't work either. I try this:
x = LinearSearch([1, 2, 3])
if (index := x.seek(1)) is not False:
    print(1, "found at", index)
else:
    print(1, "is not in list")
Output:
1 found at 0
That was found. False == 0, but False is not 0.

Even though seek() technically works, it is too easy to mess up the results. If seek() returns a non-negative integer when it succeeds, I would have it return -1 when it fails, or raise an exception (list.index() does this). Even None makes more sense than returning False.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Basic binary search algorithm - using a while loop Drone4four 1 376 Jan-22-2024, 06:34 PM
Last Post: deanhystad
  Correctly read a malformed CSV file data klllmmm 2 1,972 Jan-25-2023, 04:12 PM
Last Post: klllmmm
  Writing string to file results in one character per line RB76SFJPsJJDu3bMnwYM 4 1,388 Sep-27-2022, 01:38 PM
Last Post: buran
  Search multiple CSV files for a string or strings cubangt 7 8,063 Feb-23-2022, 12:53 AM
Last Post: Pedroski55
  Search string in mutliple .gz files SARAOOF 10 6,978 Aug-26-2021, 01:47 PM
Last Post: SARAOOF
  fuzzywuzzy search string in text file marfer 9 4,635 Aug-03-2021, 02:41 AM
Last Post: deanhystad
  I want to search a variable for a string D90 lostbit 3 2,636 Mar-31-2021, 07:14 PM
Last Post: lostbit
  platform binary representation --- 3 questions Skaperen 4 2,799 Dec-05-2020, 03:50 AM
Last Post: Skaperen
  String search in different excel Kristenl2784 0 1,711 Jul-20-2020, 02:37 PM
Last Post: Kristenl2784
  Why int() cannot pass a string representation of a float into int? majorjohnusa 1 1,902 Jul-09-2020, 05:26 AM
Last Post: Knight18

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020