From 1e4f0df9681fe24c6d10b086e98a83d56d810638 Mon Sep 17 00:00:00 2001 From: Jaime Martinez Rincon Date: Sat, 14 Jan 2017 01:20:14 +0100 Subject: [PATCH] Improved the LevenshteinDistance class --- .../utils/LevenshteinDistance.java | 104 +++++++----------- 1 file changed, 38 insertions(+), 66 deletions(-) diff --git a/src/main/java/me/jaimemartz/lobbybalancer/utils/LevenshteinDistance.java b/src/main/java/me/jaimemartz/lobbybalancer/utils/LevenshteinDistance.java index ca78e65..c9c6094 100644 --- a/src/main/java/me/jaimemartz/lobbybalancer/utils/LevenshteinDistance.java +++ b/src/main/java/me/jaimemartz/lobbybalancer/utils/LevenshteinDistance.java @@ -1,87 +1,59 @@ package me.jaimemartz.lobbybalancer.utils; public class LevenshteinDistance { - public static String getClosestString(String input, String[] options) { - int lowestDistance = 10; - String lowest = ""; + public static T closest(Iterable collection, T target) { + int distance = Integer.MAX_VALUE; + T closest = null; - for (String string : options) { - int distance = getLevenshteinDistance(input, string); - if (distance < lowestDistance) { - lowestDistance = distance; - lowest = string; + for (T object : collection) { + int current = distance(object.toString(), target.toString()); + if (current < distance) { + distance = current; + closest = object; } } - return lowest; + return closest; } - public static String getClosestString(String input, Iterable options) { - int lowestDistance = 10; - String lowest = ""; + private static int distance(CharSequence lhs, CharSequence rhs) { + int len0 = lhs.length() + 1; + int len1 = rhs.length() + 1; - for (String string : options) { - int distance = getLevenshteinDistance(input, string); - if (distance < lowestDistance) { - lowestDistance = distance; - lowest = string; - } - } + // the array of distances + int[] cost = new int[len0]; + int[] newcost = new int[len0]; - return lowest; - } + // initial cost of skipping prefix in String s0 + for (int i = 0; i < len0; i++) cost[i] = i; - private static int getLevenshteinDistance(String s, String t) { - if (s == null || t == null) { - return 11; - } + // dynamically computing the array of distances - int n = s.length(); - int m = t.length(); + // transformation cost for each letter in s1 + for (int j = 1; j < len1; j++) { + // initial cost of skipping prefix in String s1 + newcost[0] = j; - if (n == 0) { - return m; - } else if (m == 0) { - return n; - } + // transformation cost for each letter in s0 + for (int i = 1; i < len0; i++) { + // matching current letters in both strings + int match = (lhs.charAt(i - 1) == rhs.charAt(j - 1)) ? 0 : 1; - if (n > m) { - String tmp = s; - s = t; - t = tmp; - n = m; - m = t.length(); - } + // computing cost for each transformation + int cost_replace = cost[i - 1] + match; + int cost_insert = cost[i] + 1; + int cost_delete = newcost[i - 1] + 1; - int p[] = new int[n + 1]; - int d[] = new int[n + 1]; - int _d[]; - - int i; - int j; - - char t_j; - - int cost; - - for (i = 0; i <= n; i++) { - p[i] = i; - } - - for (j = 1; j <= m; j++) { - t_j = t.charAt(j - 1); - d[0] = j; - - for (i = 1; i <= n; i++) { - cost = s.charAt(i - 1) == t_j ? 0 : 1; - d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost); + // keep minimum cost + newcost[i] = Math.min(Math.min(cost_insert, cost_delete), cost_replace); } - _d = p; - p = d; - d = _d; + // swap cost/newcost arrays + int[] swap = cost; + cost = newcost; + newcost = swap; } - return p[n]; + return cost[len0 - 1]; } -} \ No newline at end of file +}