Sum of values in a multiple lists of a dict

Question:

I am new to python and have been trying to add values that I get from iterating over a list of dictionaries.

I keep running into ‘builtin_function_or_method’ object is not iterable’ error message or unsupported type. Any help would be much appreciated.

here is my code:

def inventory(acct_info, months_subscribed, add_free_months, video_on_demand):
     
  print(acct_info)


  for info in acct_info:
   
    print('-')
          
   


    
    if info.get('months_subscribed') == 3:
        months_subscribed_total = info.get('months_subscribed') * 18
    elif info.get('months_subscribed') < 3:
        months_subscribed_total = info['months_subscribed'] * 7
    elif info.get('months_subscribed') > 3:
        months_subscribed_total = info['months_subscribed'] - 3 * 7 + 18

    print(f"User {info.get('name')} has months subscribed total of : $ {months_subscribed_total} ")

    if info['ad_free_months'] > 0:

      ad_free_total = info.get('ad_free_months') * 2 
      print(f" User {info.get('name')} total ad free is : {ad_free_total} ")

    if info['video_on_demand'] > 0:
      video_on_demand_total = info.get('video_on_demand') * 27.99
      
      print(f" User {info.get('name')} total video on demand is : {video_on_demand_total} ")



      acct_all_total = int(months_subscribed_total + ad_free_total + video_on_demand_total)
      acct_all_total = [int(acct_all_total)]
      print(f"Total for {info.get('name')} is: {acct_all_total} ")  



  acct_info = [{'name': 'acct_1', 'months_subscribed' : 2 , 'ad_free_months' : 3 , 'video_on_demand' : 1} ,
                        {'name': 'acct_2', 'months_subscribed' : 1 , 'ad_free_months' : 2 , 'video_on_demand' : 2},
                        {'name': 'acct_3', 'months_subscribed' : 2 , 'ad_free_months' : 1 , 'video_on_demand' : 3}] 


  combined_total = 0
  months_subscribed = 0
  ad_free_months = 0
  video_on_demand = 0
  months_subscribed_total = 0
  ad_free_total = 0 
  video_on_demand_total = 0
  inventory(acct_info, months_subscribed, ad_free_months, video_on_demand)
  acct_all_total = 0


main()

Output so far is :

User acct_1 has months subscribed total of : $ 14 
 User acct_1 total ad free is : 6 
 User acct_1 total video on demand is : 27.99 
Total for acct_1 is: [47] 
-
User acct_2 has months subscribed total of : $ 7 
 User acct_2 total ad free is : 4 
 User acct_2 total video on demand is : 55.98 
Total for acct_2 is: [66] 
-
User acct_3 has months subscribed total of : $ 14 
 User acct_3 total ad free is : 2 
 User acct_3 total video on demand is : 83.97 
Total for acct_3 is: [99] 

What i am trying to sum up is the total for all of the users. I manage to get a total for each user, but i then want add the totals of that. Thank you.

Asked By: Nadia

||

Answers:

I modified your inventory function, now it contains a list before the loop start and it holds all the totals of the users that you are printing at the bottom of the loop, at the end using the sum function the grand total of all users can be calculated

def inventory(acct_info, months_subscribed, add_free_months, video_on_demand):
  print(acct_info)
  all_users_collection = []
  for info in acct_info:
   
    print('-')
          
    if info.get('months_subscribed') == 3:
        months_subscribed_total = info.get('months_subscribed') * 18
    elif info.get('months_subscribed') < 3:
        months_subscribed_total = info['months_subscribed'] * 7
    elif info.get('months_subscribed') > 3:
        months_subscribed_total = info['months_subscribed'] - 3 * 7 + 18

    print(f"User {info.get('name')} has months subscribed total of : $ {months_subscribed_total} ")

    if info['ad_free_months'] > 0:

      ad_free_total = info.get('ad_free_months') * 2 
      print(f" User {info.get('name')} total ad free is : {ad_free_total} ")

    if info['video_on_demand'] > 0:
      video_on_demand_total = info.get('video_on_demand') * 27.99
      
      print(f" User {info.get('name')} total video on demand is : {video_on_demand_total} ")



      acct_all_total = int(months_subscribed_total + ad_free_total + video_on_demand_total)
      acct_all_total = [int(acct_all_total)]
      all_users_collection.append(int(acct_all_total))
      print(f"Total for {info.get('name')} is: {acct_all_total} ")  



  acct_info = [{'name': 'acct_1', 'months_subscribed' : 2 , 'ad_free_months' : 3 , 'video_on_demand' : 1} ,
                        {'name': 'acct_2', 'months_subscribed' : 1 , 'ad_free_months' : 2 , 'video_on_demand' : 2},
                        {'name': 'acct_3', 'months_subscribed' : 2 , 'ad_free_months' : 1 , 'video_on_demand' : 3}] 


  combined_total = 0
  months_subscribed = 0
  ad_free_months = 0
  video_on_demand = 0
  months_subscribed_total = 0
  ad_free_total = 0 
  video_on_demand_total = 0
  inventory(acct_info, months_subscribed, ad_free_months, video_on_demand)
  acct_all_total = 0
  print('Total for all users is', sum(all_users_collection))

The other approach can be to use a single variable and increment for every total of a user at the end you will get total of all users

Answered By: Zain Ul Abidin

You can take into consideration modifying your code a little bit your code.
I would move out the for loop from your function to make it do just one thing: do the inventory for a given account.
The following code is just an example, but it provides an alternative solution for your question.

def inventory(info, months_subscribed, add_free_months, video_on_demand):
    acct_all_total = 0 # here you init the total value to 0
    if info.get('months_subscribed') == 3:
        months_subscribed_total = info.get('months_subscribed') * 18
    elif info.get('months_subscribed') < 3:
        months_subscribed_total = info['months_subscribed'] * 7
    elif info.get('months_subscribed') > 3:
        months_subscribed_total = info['months_subscribed'] - 3 * 7 + 18

    print(f"User {info.get('name')} has months subscribed total of : $ {months_subscribed_total} ")

    if info['ad_free_months'] > 0:
        ad_free_total = info.get('ad_free_months') * 2
        print(f" User {info.get('name')} total ad free is : {ad_free_total} ")

    if info['video_on_demand'] > 0:
        video_on_demand_total = info.get('video_on_demand') * 27.99

        print(f" User {info.get('name')} total video on demand is : {video_on_demand_total} ")

        acct_all_total = int(months_subscribed_total + ad_free_total + video_on_demand_total)
        # acct_all_total = [int(acct_all_total)] 
        print(f"Total for {info.get('name')} is: {acct_all_total} ")
    return acct_all_total

Please note I also commented the # acct_all_total = [int(acct_all_total)]

Then you can call it

acct_info = [{'name': 'acct_1', 'months_subscribed': 2, 'ad_free_months': 3, 'video_on_demand': 1},
             {'name': 'acct_2', 'months_subscribed': 1, 'ad_free_months': 2, 'video_on_demand': 2},
             {'name': 'acct_3', 'months_subscribed': 2, 'ad_free_months': 1, 'video_on_demand': 3}]

combined_total = 0
months_subscribed = 0
ad_free_months = 0
video_on_demand = 0
months_subscribed_total = 0
ad_free_total = 0
video_on_demand_total = 0
acct_all_total = 0
for acct in acct_info:
    acct_all_total+=inventory(acct, months_subscribed, ad_free_months, video_on_demand)
print("Tot:",acct_all_total)

Output:

User acct_1 has months subscribed total of : $ 14 
 User acct_1 total ad free is : 6 
 User acct_1 total video on demand is : 27.99 
Total for acct_1 is: 47 
User acct_2 has months subscribed total of : $ 7 
 User acct_2 total ad free is : 4 
 User acct_2 total video on demand is : 55.98 
Total for acct_2 is: 66 
User acct_3 has months subscribed total of : $ 14 
 User acct_3 total ad free is : 2 
 User acct_3 total video on demand is : 83.97 
Total for acct_3 is: 99 
Tot: 212

Edited to reflect comments.

If you want to get the largest of your total, you have to change the code a bit. Consider to use the built-in function max() https://docs.python.org/3.8/library/functions.html#max and sum() https://docs.python.org/3.8/library/functions.html#sum.

max() returns the largest item in an iterable or the largest of two or more arguments. sum() sums all the element in an iterable. So, let’s use an iterable in our code

 tot = list() 
for acct in acct_info:
    # here, we gonna append each total
    tot.append(inventory(acct, months_subscribed, ad_free_months, video_on_demand))
print("all the values:",tot)
print("the largest is:",max(tot)) # here we extract the largest item of the list
print("Total:",sum(tot)) # here we sum all the element of the list tot

Output:

all the values: [47, 66, 99]
the largest is: 99
Total: 212
Answered By: hellbreak
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.