Вот мое решение. Он работает со всеми приведенными вами примерами и предполагает сортировку входного массива.
Обратите внимание, что он не выглядит исключительно для чисел; он ищет согласованную последовательность символов, которая может отличаться во всех строках. Поэтому, если вы укажете {"0000", "0001", "0002"}
, он вернет «0» и «2» в качестве начальной и конечной строк, поскольку это единственная часть строк, которая отличается. Если вы дадите ему {"0000", "0010", "0100"}
, он вернет вам «00» и «10».
Но если вы дадите ему {"0000", "0101"}
, он будет скулить, поскольку различные части строки не являются смежными. Если вы хотите изменить это поведение, чтобы оно возвращало все от первого отличающегося символа до последнего, это нормально; Я могу сделать это изменение. Но если вы передаете ему тонну имен файлов, которые будут иметь последовательные изменения в области номеров, это не должно быть проблемой.
public static class RangeFinder
{
public static void FindRange(IEnumerable<string> strings,
out string startRange, out string endRange)
{
using (var e = strings.GetEnumerator()) {
if (!e.MoveNext())
throw new ArgumentException("strings", "No elements.");
if (e.Current == null)
throw new ArgumentException("strings",
"Null element encountered at index 0.");
var template = e.Current;
// If an element in here is true, it means that index differs.
var matchMatrix = new bool[template.Length];
int index = 1;
string last = null;
while (e.MoveNext()) {
if (e.Current == null)
throw new ArgumentException("strings",
"Null element encountered at index " + index + ".");
last = e.Current;
if (last.Length != template.Length)
throw new ArgumentException("strings",
"Element at index " + index + " has incorrect length.");
for (int i = 0; i < template.Length; i++)
if (last[i] != template[i])
matchMatrix[i] = true;
}
// Verify the matrix:
// * There must be at least one true value.
// * All true values must be consecutive.
int start = -1;
int end = -1;
for (int i = 0; i < matchMatrix.Length; i++) {
if (matchMatrix[i]) {
if (end != -1)
throw new ArgumentException("strings",
"Inconsistent match matrix; no usable pattern discovered.");
if (start == -1)
start = i;
} else {
if (start != -1 && end == -1)
end = i;
}
}
if (start == -1)
throw new ArgumentException("strings",
"Strings did not vary; no usable pattern discovered.");
if (end == -1)
end = matchMatrix.Length;
startRange = template.Substring(start, end - start);
endRange = last.Substring(start, end - start);
}
}
}