protected static PairResult MatchOneRow(T todo, object objshr) { MatchShared shared = (MatchShared)objshr; BestScore <T> one_to_all = new BestScore <T>(); // start by looking at all results for one's row foreach (T two in shared.twos) { double score = shared.comparisons.Evaluate(new TwoTuple <T, T>(todo, two), shared); one_to_all.Improve(score, two); } if (one_to_all.payload == null || one_to_all.payload.Equals(default(T))) { // no more results! Return empty match. shared.ones = new SkipEnumerable <T>(shared.ones, todo); return(new PairResult(double.NegativeInfinity, todo, default(T))); } // Now look at all other entries in that column BestScore <T> match_to_others = new BestScore <T>(one_to_all.score, todo); foreach (T one in shared.ones) { if (!one.Equals(todo)) { double score = shared.comparisons.Evaluate(new TwoTuple <T, T>(one, one_to_all.payload), shared); match_to_others.Improve(score, one); } } if (match_to_others.payload.Equals(todo)) { // remove this row and column shared.ones = new SkipEnumerable <T>(shared.ones, todo); shared.twos = new SkipEnumerable <T>(shared.twos, one_to_all.payload); return(new PairResult(one_to_all.score, todo, one_to_all.payload)); } else { // First do the row we found! shared.matches.Evaluate(match_to_others.payload, shared); // Then do this one again! return(MatchOneRow(todo, shared)); } }
// Find the best matches, ensuring one entry for every element in ones public static IEnumerable <PairResult> LeftMatch(IEnumerable <T> ones, IEnumerable <T> twos, MatchScorer scorer, object objshr) { MatchShared shared = new MatchShared(); shared.objshr = objshr; shared.matches = new Memoizer <T, PairResult>(MatchOneRow); shared.comparisons = new Memoizer <TwoTuple <T, T>, double>(MatchComparison); shared.scorer = scorer; shared.ones = ones; shared.twos = twos; foreach (T one in ones) { shared.matches.Evaluate(one, shared); } return(shared.matches.Results.Values); }
protected static double MatchComparison(TwoTuple <T, T> onetwo, object objshr) { MatchShared shared = (MatchShared)objshr; return(shared.scorer(onetwo.one, onetwo.two, shared.objshr)); }