这是我的解决方案。它适用于您提供的所有示例,并且它假定输入数组已排序。
请注意,它并非专门针对数字;它查找可能在所有字符串中不同的一致字符序列。因此,如果您向它提供{"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);
}
}
}