Reputation: 9233
I know this is a ridiculous example, but I'm looking for a more efficient way to write this code. Each project gets different values added to it depending on what state it takes place in. This is just a small snippet. I could potentially want to extend this out for all 50 states, which would be a lot of if statements. I could dump this in a function, but then the function would still have all the if statements.
Projects = [['Project A', 'CT', '', ''], ['Project B', 'MA', '', ''], ['Project C', 'RI', '', '']]
for project in Projects:
if project[1] == 'CT':
project[2] = project[0] + project[1]
project[3] = '222'
elif project[1] == 'MA':
project[2] = '123'
project[3] = None
elif project[1] == 'ME':
project[2] = '12323'
project[3] = '333'
elif project[1] == 'RI':
project[2] = 'asdf'
project[3] = '3333'
print Projects
Upvotes: 2
Views: 246
Reputation: 122086
To expand on my comment and mescalinum's answer, if some of the impacts on project[2]
will be derived from other values in the project
, you can put callable objects (e.g. by using lambda
expressions) in the dictionary:
IMPACTS = {
'CT': (lambda project: project[0] + project[1], '222'),
'MA': ('123', None),
...,
}
Then you can apply it like:
for project in Projects:
two, three = IMPACTS[project[1]]
try:
project[2] = two(project)
except TypeError:
project[2] = two
project[3] = three
If some of project[3]
's values will vary, you can similarly make them callable in the dictionary and apply the same try
/except
logic (or if callable(...)
) to filter those that need calling.
Upvotes: 2
Reputation: 18950
Using a dictionary mapping:
for project in Projects:
project[2:4] = {
'CT': [project[0]+project[1], '222'],
'MA': ['123', None],
'ME': ['12323', '333'],
'RI': ['asdf', '3333']
}[project[1]]
removes all the if
/else
, and just deals with real data :)
As suggested by jonrsharpe, it may be more efficient delaying the evaluation of the dictionary values with lambda
s (at the cost of writing more):
for project in Projects:
project[2:4] = {
'CT': lambda: [project[0]+project[1], '222'],
'MA': lambda: ['123', None],
'ME': lambda: ['12323', '333'],
'RI': lambda: ['asdf', '3333']
}[project[1]]()
Edit: explanation for user2242044:
consider the function:
def foo(x):
print('*** foo(%s)' % x)
return x
and see what happens when you do:
>>> {1: foo(1), 2: foo(2)}[1]
*** foo(1)
*** foo(2)
1
as you see, it computes all the values in dictionary, calling both foo(1)
and foo(2)
, for then just using the value of foo(1)
.
With lambda
s:
>>> {1: lambda: foo(1), 2: lambda: foo(2)}[1]()
*** foo(1)
1
the dictionary returns a function, and when you call the function, the value is computed, thus computing only the value of foo(1)
Upvotes: 8