0

I have this code block that assigns an account type based on a list of acccount names. But it fails if an account name is not in any of the 'name' arrays.

How do I add a "default" type if not found? Or is there a more elegant way to do this?

accts = [
    {'id': 1425396, 'name': 'Banana'}, 
    {'id': 1425399, 'name': 'Schwab Brokerage'}, 
    {'id': 1425400, 'name': 'Schwab'}, 
    {'id': 1425411, 'name': 'CapitalOne'}, 
    {'id': 1425428, 'name': '401K'}, 
    {'id': 1425424, 'name': 'Venmo'}, 
    {'id': 1425428, 'name': 'Geico'}, 
    {'id': 1425428, 'name': 'PayPal'}, 
    {'id': 1426349, 'name': 'Coinbase'},
    {'id': 1426349, 'name': 'XXX'}
]

for acct in accts: acct['acct_type'] = next(acct_type for acct_type in 
   [
      {'acct_type':'checking', 'accts':['Schwab','Venmo']},
      {'acct_type':'credit', 'accts':['Banana','CapitalOne']},
      {'acct_type':'other', 'accts':['Geico','PayPal']},
      {'acct_type':'invest', 'accts':['Schwab Brokerage','401K','Coinbase']}
   ]
   if acct['name'] in acct_type['accts'])['acct_type']

The last (XXX) account causes this:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
Dan
  • 1,257
  • 2
  • 15
  • 31
  • please provide minimal reproducible code and refrain from using reserved words – Epsi95 Aug 03 '21 at 15:40
  • @Epsi95 Sorry, where did I use a reserved word? (Not seeing anything from `help("keywords")`) And what do you mean 'minimal reproducible code'? – Dan Aug 03 '21 at 15:48
  • 1
    `type` it is not a reserved word but builtin function and what I wanted say is to give some code that can be copied and reproduced easily – Epsi95 Aug 03 '21 at 15:51

2 Answers2

1

You could simply replace the list-of-dicts lookup with a dictionary. For example:

acct_types = {
    "Schwab": "checking", "Venmo": "checking",
    "Banana": "credit", "CapitalOne": "credit",
    "Geico": "other", "PayPal": "other",
    "Schwab Brokerage": "invest", "401K": "invest", "Coinbase": "invest"
}

Then, all you need to do is lookup in this dictionary using the .get() function. The second argument provides the default value.

for acct in accts: 
    acct['acct_type'] = acct_types.get(acct['name'], "other")

Which gives the expected result:

[{'id': 1425396, 'name': 'Banana', 'acct_type': 'credit'},
 {'id': 1425399, 'name': 'Schwab Brokerage', 'acct_type': 'invest'},
 {'id': 1425400, 'name': 'Schwab', 'acct_type': 'checking'},
 {'id': 1425411, 'name': 'CapitalOne', 'acct_type': 'credit'},
 {'id': 1425428, 'name': '401K', 'acct_type': 'invest'},
 {'id': 1425424, 'name': 'Venmo', 'acct_type': 'checking'},
 {'id': 1425428, 'name': 'Geico', 'acct_type': 'other'},
 {'id': 1425428, 'name': 'PayPal', 'acct_type': 'other'},
 {'id': 1426349, 'name': 'Coinbase', 'acct_type': 'invest'},
 {'id': 1426349, 'name': 'XXX', 'acct_type': 'other'}]

If you don't want to manually create the acct_types dictionary, you can easily convert the list-of-dicts that you already have:

lookup = [
      {'acct_type':'checking', 'accts':['Schwab','Venmo']},
      {'acct_type':'credit', 'accts':['Banana','CapitalOne']},
      {'acct_type':'other', 'accts':['Geico','PayPal']},
      {'acct_type':'invest', 'accts':['Schwab Brokerage','401K','Coinbase']}
   ]

acct_types = dict()
for item in lookup:
    for acct_name in item['accts']:
        acct_types[acct_name] = item['acct_type']
Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
0

I figured it out, using the default parameter of next():

for acct in accts: acct['acct_type'] = next(
   (
      acct_type for acct_type in 
      [
         {'acct_type':'checking', 'accts':['Schwab','Venmo']},
         {'acct_type':'credit', 'accts':['Banana','CapitalOne']},
         {'acct_type':'other', 'accts':['Geico','PayPal']},
         {'acct_type':'invest', 'accts':['Schwab Brokerage','401K','Coinbase']}
      ]
      if acct['name'] in acct_type['accts']
   ),
   {'acct_type':'other'}
)['acct_type']
Dan
  • 1,257
  • 2
  • 15
  • 31