Reputation: 8481
I'm working on a piece of code that needs to validate whether two users are "matched" under several different criteria. If it helps, think of this as a dating app, where we are trying to match people based on age, sexual preference, ethnicity preference, etc. Here's an example with 3 conditions, each of which is a function.
def is_match(row):
return True \
and ethnicity(user_a, user_b) \
and sexual_orientation(user_a, user_b) \
and age(user_a, user_b) \
Now, let's say I want to add another condition for proximity, I would just add it to the function:
def is_match(row):
return True \
and ethnicity(user_a, user_b) \
and sexual_orientation(user_a, user_b) \
and age(user_a, user_b) \
and proximity(user_a, user_b)
Of course, this is feasible for a small application, but I can imagine a point where other co-workers may want to check out the code and pass their own conditions to it, and this doesn't seem abstract enough. I know there must be a pattern here to follow. Should I pass in each function as an array? How would you recommend doing this? I'm working in Python, but you can use any language you want to demonstrate the patterns.
Upvotes: 1
Views: 1738
Reputation: 2677
def is_match(list_of_functions, user_a, user_b):
return all([cur_fun(user_a, user_b) for cur_fun in list_of_functions])
Edit:
The following variant is more efficient, since it short-circuits the moment it hits a non-True value, rather than necessarily evaluating all of the functions:
def is_match(list_of_functions, user_a, user_b):
for cur_fun in list_of_functions
if not cur_fun(user_a, user_b):
return False
return True
Upvotes: 1
Reputation: 1340
I think sets are good for such tasks, because it's rather comparsion than validation. I will give You example:
user_a = {
'ethnicity': 1,
'sexual_orientation': 'straight',
'age': 37,
}
user_b = {
'ethnicity': 2,
'sexual_orientation': 'straight',
'age': 34,
}
differences = set(user_a.items()) ^ set(user_b.items()) # s.symmetric_difference(t)
commons = set(user_a.items()) & set(user_b.items()) # s.intersection(t)
print({'differences': differences, 'commons': commons})
output:
{'differences': {('ethnicity', 2), ('ethnicity', 1), ('age', 37), ('age', 34)}, 'commons': {('sexual_orientation', 'straight')}}
So You could just load data of two users to dicts and compare.
Upvotes: 2
Reputation: 3533
Checkout the Specification Pattern. This is exactly what you need. Its written in C# but can be easily converted
Upvotes: 1