Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I return the number of stock sold and bought without defaultdict?

For this problem, we are given this dictionary whose keys are names; which has tuples with 3 values: in the 3-tuple, a stock name, number of shares traded for that transaction (int), and price of each share (int).

new_dict = {
    'Carl': [('Intel', 30, 40), ('Dell' , 20, 50), ('Intel',-10, 60), 
('Apple', 20, 55)],
    'Barb': [('Intel', 20, 40), ('Intel',-10, 45), ('IBM',   40, 30), 
('Intel',-10, 35)],
    'Alan': [('Intel', 20, 10), ('Dell',  10, 50), ('Apple', 80, 80), ('Dell', 

-10, 55)],
    'Dawn': [('Apple', 40, 80), ('Apple' ,40, 85), ('Apple',-40, 90)]
  }

I am creating a traded function that takes in new_dict and returns a dictionary where keys are all the stocks that appear in transactions; the value is a stock is a 2-list where the first index is the number of shares of that stock bought and whose second index is the number of shares of that stock sold. Bought is positive stock and sold is any stock with a negative number.

The output of this function should be:

{'Intel': [70, 30], 'Dell': [30, 10], 'Apple': [180, 40], 'IBM': [40, 0]}

This is what I have so far:

def traded(database :{str: (str, int, int)}) ->dict:
    result_dict = dict()
    intel = []
    dell = []
    apple = []
    ibm = []



    for key, val in database.items():
        pos_sum = 0
        for x in val:
            if x[1] > 0:
               pos_sum += x[1]

    return pos_sum

I am trying to do this for each stock company individually by having separate lists for each stock company, but I feel that is just tedious. I'm not sure what other techniques there are to do this for each stock company individually.

Is there a simple, easy to understand way to do this, preferably without defaultdict?

Thanks!

like image 928
generation_coding Avatar asked Dec 05 '25 04:12

generation_coding


2 Answers

This should work for you (although there is certainly a more compact way) :

stock_dict = {}
for user_list in new_dict.values():
    for stock_tuple in user_list:
        stock_name = stock_tuple[0]
        if (not (stock_name in stock_dict.keys())):
            stock_dict[stock_name] = list(stock_tuple[1:])
        else:
            stock_dict[stock_name][0] += stock_tuple[1]
            stock_dict[stock_name][1] -= stock_tuple[2]
  • You could also zip and sum, but its less intuitive.

Basically what you do is create a value for the specific key (if it doesn't exist - this part is only necessary because you dont want to use a default dict), and if it does exist you add the relevant values.

like image 122
Rohi Avatar answered Dec 07 '25 18:12

Rohi


Instead of defaultdict you can use dict.setdefault:

d = {}

for k, v in new_dict.items():
    for company, shares, price in v:
        if shares > 0:
            d.setdefault(company, [0, 0])[0] += shares
        else:
            d.setdefault(company, [0, 0])[1] -= shares

Result

{'Apple': [180, 40], 'Dell': [30, 10], 'IBM': [40, 0], 'Intel': [70, 30]}

Explanation

  • Set default value for dictionary items to [0, 0].
  • Then we can iterate new_dict and increment shares at the appropriate index.
  • For shares sold we must negate in order to extract a positive result.

defaultdict solution

from collections import defaultdict

d = defaultdict(lambda: [0, 0])

for k, v in new_dict.items():
    for company, shares, price in v:
        if shares > 0:
            d[company][0] += shares
        else:
            d[company][1] -= shares
like image 26
jpp Avatar answered Dec 07 '25 18:12

jpp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!