Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting instances of an Object by Numeric values Python

I'm scraping a website for certain values like name, price, stock and rating and have been using the functions

    my_products.sort(key = lambda x: x.return_name())
    my_products.sort(key = lambda x: x.return_price())
    my_products.sort(key = lambda x: x.return_rating())
    my_products.sort(key = lambda x: x.return_stock())

to sort them. It all works fine and dandy, except it doesn't sort the price numerically, it lists them like 1000, 1500, 20, 200, 2000, 2500. Which isn't exactly what I'm looking for. How can I change this sorting behavior?

The class for each product:

class Product():
__title = ""
__price = ""
__rating =""
__stock = ""

def __init__(self,title, price, rating, stock):
    self.__title = title
    self.__price = price
    self.__rating = rating
    self.__stock = stock

def toString(self):
    return "Title: {}\nPrice: {}\nRating: {}\nStock: {}\n".format(  self.__title,
                                                                    self.__price,
                                                                    self.__rating,
                                                                    self.__stock)

def return_price(self):
    return self.__price

def return_name(self):
    return self.__title

def return_rating(self):
    return self.__rating

def return_stock(self):
    return self.__stock
like image 298
Peebl Avatar asked Dec 18 '25 20:12

Peebl


2 Answers

As you write it in your class, price is a string, then all prices will be compared like strings. You have two options:

  1. Convert price into the sorting function : my_products.sort(key = lambda x: float(x.return_price())).
    note that you can convert either by int() or float()
  2. Declare price directly as a numeric (and don't change the sorting syntax):

    class Product():
        __title = ""
        __price = np.nan
        __rating =""
        __stock = ""
    
        def __init__(self,title, price, rating, stock):
            self.__title = title
            #---
            self.__price = price#if price is a numeric input
            #or convert to the right type if price is a string input
            self.__price = float(price)
            #---
            self.__rating = rating
            self.__stock = stock
    

In my opinion I would use the option 2 to stay coherent with the meaning of the values. Note that you should rewrite your functions accordingly to new types.
Maybe you could do the same with your ratings / stocks (if it is numeric too).

EDIT - String comparison and sorting
To compare string python convert characters into their ordinal equivalent then check int from left to right. So '1000' is lower than '20', see below:

print('1000 : %d' %sum(ord(i) for i in '1000'))
print('1500 : %d' %sum(ord(i) for i in '1500'))
print('20 : %d' %sum(ord(i) for i in '20'))

#output
1000 : 193
1500 : 198
20 : 98
like image 169
David Leon Avatar answered Dec 21 '25 11:12

David Leon


Just convert strings to numbers (e.g. int or float) in your key function:

my_products.sort(key = lambda x: float(x.return_price()))

You could also update the method so that it returns a number in the first place:

def return_price(self):
    return float(self.__price)
like image 25
Eugene Yarmash Avatar answered Dec 21 '25 12:12

Eugene Yarmash