fork download
  1. import re
  2.  
  3. def fuzzy_filter(patterns, names):
  4. def match(pattern, words_index=0, pattern_index=0, word_index=0):
  5. return pattern_index == len(pattern) or (
  6. words_index < len(words) and word_index < len(words[words_index])
  7. ) and (
  8. pattern[pattern_index] == words[words_index][word_index] and (
  9. match(pattern, words_index, pattern_index + 1, word_index + 1) or
  10. match(pattern, words_index + 1, pattern_index + 1)
  11. ) or match(pattern, words_index + 1)
  12. )
  13.  
  14. for name in names:
  15. words = list(map(str.lower, re.split(r'[\W_]+|(?<=\w)(?=[A-Z])', name)))
  16. if all(map(match, patterns.split())):
  17. yield name
  18.  
  19. file_names = [
  20. 'HelloWorld.csv',
  21. 'hello_windsor.pdf',
  22. 'some_file_i_need.jpg',
  23. 'san_francisco.png',
  24. 'Another.file.txt',
  25. 'A file name.rar'
  26. ]
  27.  
  28. queries = '''\
  29. hw
  30. hwor
  31. winds
  32. sf
  33. file need
  34. sfr
  35. file
  36. file another
  37. fnrar'''.splitlines()
  38.  
  39. for query in queries:
  40. print(f'{query} -> {", ".join(fuzzy_filter(query, file_names))}')
Success #stdin #stdout 0.04s 9732KB
stdin
Standard input is empty
stdout
hw -> HelloWorld.csv, hello_windsor.pdf
hwor -> HelloWorld.csv
winds -> hello_windsor.pdf
sf -> some_file_i_need.jpg, san_francisco.png
file need -> some_file_i_need.jpg
sfr -> san_francisco.png
file -> some_file_i_need.jpg, Another.file.txt, A file name.rar
file another -> Another.file.txt
fnrar -> A file name.rar