Я хочу сравнить список строк друг с другом с помощью Damerau до Levenshtein Distance
В настоящее время у меня есть:
char lastchar = (char)('z'+1);
SimilarStrings similarStrings = new SimilarStrings();
List<String> listString = new List<string>();
listString.Add("Rammstein");
listString.Add("Ramstein");
listString.Add("Rammsten");
listString.Add("Metallica");
listString.Add("Metalica");
listString.Add("Metaica");
for (int i = 0; i < listString.Count(); i++)
{
for(int n = 0; n < listString.Count(); n++)
{
String str1 = String.Copy(listString[i]);
String str2 = String.Copy(listString[n]);
Console.Write(str1); Console.Write(" to "); Console.Write(str2 + "\n");
int DADistance = SimilarStrings.damerauLevenshteinDistance(str1, str2, (int)lastchar);
Console.WriteLine(DADistance);
}
}
Это прекрасно работает, единственная проблема заключается в том, что каждое сравнение выполняется дважды. Это означает, что "Rammstein" сравнивается с "Metallica", а затем "Metallica" снова сравнивается с "Rammstein". Половины сравнения было бы достаточно. Но как мне это сделать в хорошей форме? Я могу только подумать о некоторых сложных способах.
Стандартный способ - запустить внутренний цикл из индекса внешнего цикла плюс один.
for (int i = 0; i < listString.Count(); i++)
for (int n = i + 1; n < listString.Count(); n++)
Это предполагает, что вы не хотите сравнивать каждую строку с самим собой - если вы это сделаете, удалите + 1
.
Вот пример логики. Если ваш список был: abcd
, вы бы хотели сравнить a
с:
a <> b
a <> c
a <> d
Для b
вам не нужно сравнивать b
с a
, потому что вы уже сравнили a
со всем. Итак, вы можете начать с c
:
b <> c
b <> d
И для c
вы уже сравнили a
и b
со всем, поэтому вы можете начать с d
:
c <> d
Поэтому каждый элемент нужно сравнить только с элементами после него в списке - это то, что выражается вложенными циклами выше.
Это должно предотвратить дублирование сравнений
for (int i = 0; i < listString.Count(); i++)
{
for(int n = i + 1; n < listString.Count(); n++)
{
...
}
}