Yogesh Riyat
Yogesh Riyat

Reputation: 131

When using findall, TypeError: expected string or bytes-like object

I am trying to implement this class and I am having trouble with the getPostFix method. I don't understand how to fix the error that I am getting.

This is the str method in the class just for reference.

    # Returns the string representation of the Calc.
    def __str__(self):
        
        theCalc = ""
        theCalc += 'Input is: ' + self.getInput() + '\n'
        theCalc += 'Postfix input is: ' + self.getPostFix() + '\n'
        theCalc += 'Value is: ' + str(self.evaluate()) + '\n'
        
        return theCalc  

This is where I am getting the error.

    def getPostFix(self):

        result = ""

        # stack used to create postfix string
        self.stack = MyStack()

        input_string = self.getInput()
        input_string_split = [x for x in re.split("(\d*\.?\d*)", input_string) if x != '']
        numbers = re.findall('([0-9.]+)', input_string_split, re.DOTALL)

        for i in input_string_split:

            if i in numbers:
                result += i


            elif isOperator(i):
                while True:
                    topItem = self.stack.getTop()
                    if self.stack.size == 0 or topItem == '(':
                        self.stack.push(i)
                        break
                    else:
                        precedence_i = getPrecedence(i)
                        precedence_topItem = getPrecedence(topItem)

                        if precedence_i > precedence_topItem:
                            self.stack.push(i)
                            break
                        else:
                            ipop = self.stack.pop()
                            result += ipop if ipop else ""
                            #result += self.stack.pop()

            elif i == '(':
                self.stack.push(i)

            elif i == ')':
                ipop = self.stack.pop()

                while ipop != '(':
                    result += ipop if ipop else ""
                    ipop = self.stack.pop()

            elif i == '=':
                ipop = self.stack.pop()
                result += ipop if ipop else ""
                #result += self.stack.pop()

        while not self.stack.size == 0:
            ipop = self.stack.pop()
            result += ipop if ipop else ""

        return result

And here is the error. It says it's expecting a string, but isn't input_string_split a list of strings? I don't understand how to fix it.

Traceback (most recent call last):
  File "xxx", line 9, in <module>
    print(calc)
  File "xxx", line 23, in __str__
    theCalc += 'Postfix input is: ' + self.getPostFix() + '\n'
  File "xxx", line 50, in getPostFix
    numbers = re.findall('([0-9.]+)', input_string_split, re.DOTALL)
  File "/usr/local/Cellar/[email protected]/3.9.2_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/re.py", line 241, in findall
    return _compile(pattern, flags).findall(string)
TypeError: expected string or bytes-like object

I am updating to show my attempt at using @Xinthral's answer below. I added a helper function:

def isOperand(c):
    number = re.search('([0-9.]+)', c)
    if number != None:
        return True
    else:
        return False

so now the if statement in the for loop is:

if isOperand(i):
  result += (i + ' ')

But I get the output below which indicates to me that the rest of the for loop is not being executed. That is, it is not iterating through the list and finding operators or parentheses etc.

Input is: 3.2+.4*5.67/6.145=
Postfix input is: 3.2 .4 5.67 6.145 
Value is: None

Input is: 11.897/3.4+9.2-0.4*6.9/12.6-16.7=
Postfix input is: 11.897 3.4 9.2 0.4 6.9 12.6 16.7 
Value is: None

Input is: 234+34*65=
Postfix input is: 234 34 65 
Value is: None

Upvotes: 0

Views: 949

Answers (1)

Xinthral
Xinthral

Reputation: 437

The following should help, I think the logic is just out of order. Your for loop is already going over the whole 'input_string_split', so check each line would be checked during the loop. Hopefully this helps, let me know.

Before:

input_string_split = [x for x in re.split("(\d*\.?\d*)", input_string) if x != '']
numbers = re.findall('([0-9.]+)', input_string_split, re.DOTALL)

for i in input_string_split:
  if i in numbers:
    result += i

After:

input_string_split = [x for x in re.split("(\d*\.?\d*)", input_string) if x != '']
numbers = list()

for i in input_string_split:
  number = re.search('([0-9.]+)', i)
  if number != None: 
    numbers.append(i)
    result += i

Upvotes: 1

Related Questions