<s> import difflib <EOL> class RecommendationFinder ( object ) : <EOL> def __init__ ( self , normalizer = None ) : <EOL> self . normalizer = normalizer or ( lambda x : x ) <EOL> def find_recommendations ( self , name , candidates , max_matches = <NUM_LIT:10> ) : <EOL> """<STR_LIT>""" <EOL> if not name or not candidates : <EOL> return [ ] <EOL> norm_name = self . normalizer ( name ) <EOL> norm_candidates = self . _get_normalized_candidates ( candidates ) <EOL> cutoff = self . _calculate_cutoff ( norm_name ) <EOL> norm_matches = difflib . get_close_matches ( norm_name , <EOL> norm_candidates , <EOL> n = max_matches , <EOL> cutoff = cutoff ) <EOL> return self . _get_original_candidates ( norm_candidates , norm_matches ) <EOL> @ staticmethod <EOL> def format_recommendations ( msg , recommendations ) : <EOL> """<STR_LIT>""" <EOL> if recommendations : <EOL> msg += "<STR_LIT>" <EOL> for rec in recommendations : <EOL> msg += "<STR_LIT>" % rec <EOL> return msg <EOL> def _get_normalized_candidates ( self , candidates ) : <EOL> norm_candidates = { } <EOL> for cand in sorted ( candidates ) : <EOL> norm = self . normalizer ( cand ) <EOL> norm_candidates . setdefault ( norm , [ ] ) . append ( cand ) <EOL> return norm_candidates <EOL> def _get_original_candidates ( self , norm_candidates , norm_matches ) : <EOL> candidates = [ ] <EOL> for norm_match in norm_matches : <EOL> candidates . extend ( norm_candidates [ norm_match ] ) <EOL> return candidates <EOL> def _calculate_cutoff ( self , string , min_cutoff = <NUM_LIT> , max_cutoff = <NUM_LIT> , <EOL> step = <NUM_LIT> ) : <EOL> """<STR_LIT>""" <EOL> cutoff = min_cutoff + len ( string ) * step <EOL> return min ( cutoff , max_cutoff ) </s>
