Anche senza considerare le date di nascita, puoi procedere in questa maniera:
- parti dai nomi propri, che hanno la minima variabilità interna al gruppo; costruisci una hashtable da nome (tutto minuscolo) a lista di id in cui compare;
- la hashtable in questione, dato che i nomi propri sono pochi, è più che gestibile a livello di confronti, per cui puoi tranquillamente fare il confronto "tutti contro tutti" (o meglio, l'elemento x con tutti gli elementi che lo seguono, quindi in tutto n*(n-1)/2 confronti);
- stabilita una soglia sotto cui dai come "probabile" il match, se l'elemento a è "simile" all'elemento b puoi procedere a fare il check con i cognomi, che vai a cercare in base all'ID del record; rispetto al caso "tutti contro tutti in generale" hai ucciso il fattore O(n^2) sui cognomi, che è il problema principale.
Riassumo il procedimento descritto sopra in pseudo-Python:
codice:
from collections import defaultdict
data = [{}] # cursore sul DB
names = {}
surnames = {}
matches = []
for elem in data:
n = elem.name.strip().lower()
l = names.setdefault(n, [])
l.append(elem.id)
surnames[elem.id] = elem.surname
for k,v in names:
found = False
for kk,vv in names:
if not found:
if k==kk:
found = True
else:
continue
if similar(k, kk):
for id1 in v:
for id2 in vv:
if similar(surnames[id1], surnames[id2]):
matches.append((id1, id2))
# ora in matches hai le coppie di ID di record con nome e cognome simile
Si possono usare anche le date di nascita per scremare a priori, ma sarebbe da capire meglio come le hai memorizzate.