How do I use a variable as an array index in Python?

Viewed 91

I have 2 classes, Product and Transaction.
Each Product object represents a product that is sold, and each Transaction object represents how much of that product was sold.

I am making an array of Product objects called product_list and an array of Transaction objects called transaction_list. Both classes have an attribute called ProductID, which is a string of some characters like "ABCDE". What I need to do is add data from each Transaction object to attributes of the Product objects.

Currently, I have an attribute in the Transaction object called product_list_index that would be the same as the index of the Product object in the product_list array that has the same ProductID as the given Transaction object.

My approach was going to be to iterate through every transaction in the array, and set the product_list_index of each Transaction object to the index of whichever Product object had the matching ProductID attribute. So when I add data to the Product object, it would be like this:

x = 1(this would be data from the transaction)

product_list[product_list_index].total_gallons_sold_of_this_product += x

Is there a better way to link the objects together based on a variable instead of iterating through every one to find the correct index?

Here is a minimum example of my code (there's a lot cut out to make it eaiser to read):

class Product:
   def __init__ (self, productID)
      self.brandName = ""
      self.productID = str(productID)
      self.total_gallons_sold_of_this_product = 0
      self.total_gallons_sold_to_retailers = 0
      self.total_gallons_sold_to_customers = 0

class Transaction:
   def __init__ (self, productID)
      self.productID = str(productID)
      self.total_gallons_for_this_sale = 0  # gets input from generate_transaction_list function
      self.is_retailer_sale = 0  # boolean, if it's not a retailer sale then it's a customer sale

def generate_transaction_list():  # Makes an array of Transaction objects from an excel spreadsheet, uses a pandas dataframe, returns the array
...
def generate_product_list():  # Makes an array of the different products based on an excel spreadsheet, returns the array
...

array_transaction_data = generate_transaction_list()
product_list = generate_product_list()

2 Answers

Let Transaction have a Product instance instead productId:

class Transaction:
    def __init__(self, product):
        self.product = product

Then you can:

def generate_product_list():
    productId2Product = {}
    ...  # reading from file
        productId2Product[productId] = Product(productId)
    return productId2Product


def generate_transaction_list(productId2Product):
    transaction_list = []
    ...  # reading from file
        transaction_list.append(Product(productId2Product[productId]))
    return transaction_list
     

productId2Product = generate_product_list()

array_transaction_data = generate_transaction_list(productId2Product)

array_transaction_data[i].product.total_gallons_sold_of_this_product += x

This sort of problem is an ideal use-case for a dictionary. A dictionary is a lot like an array, but instead of using sequential numbers 0, 1, 2... as keys (which would be an array) you can use arbitrary strings. So you can have, for example,

products = {
    '1a1a': MyDrillObject,
    '2b2b': MyScrewsProduct,
    'fffee': MyTowelProduct
}

and then to retrieve a specific object representing a product you can do, for example,

drill_obj = products['1a1a']

And this lookup is efficient, it doesn't iterate through all the keys in the dictionary.

So to solve your problem, you could do away with your product list index and instead use the ProductID as the dictionary key directly.

This would do simplify the preprocessing step down to just adding all the products to the product dictionary:

product_dict = {p.ProductID: p for p in products}

and then when processing transactions, you can use the productID directly:

product_dict[transaction.ProductID].total_gallons_sold_of_this_product += x
Related