我想从已排序的 {{1}自动解析 范围 编号序列通过检查文件名的哪一部分发生变化来修改文件名。
以下是一个示例(文件扩展名已被删除):
第一个文件名:
List<FileData>
上次文件名:IMG_0000
我需要的编号范围:IMG_1000
和0000
除了我需要处理每种可能类型的文件命名约定,例如:
<00> 0000 ... 9999
20080312_0000 ... 20080312_9999
IMG_0000 - 复制... IMG_9999 - 复制
8er_green3_00001 .. 8er_green3_09999
等
1000
不只是0001
1
0001
IMG_0000 - Copy
开头,以1
结束9999
每当我为8个随机测试用例工作时,第9次测试会破坏所有内容,最后我会从头开始重新开始。
我目前一直在比较仅第一个和最后一个文件名(而不是遍历所有文件名):
20080312_0000
有没有人有任何聪明的想法?也许是Regex的东西?
答案 0 :(得分:1)
如果您确定知道文件以数字结尾(例如_ \ _d +),并且已经排序,只需抓住第一个和最后一个元素,这就是您的范围。如果文件名都相同,您可以对列表进行排序,以便按数字顺序排列它们。除非我在这里遗漏了一些明显的东西 - 问题在哪里?
答案 1 :(得分:1)
首先,我将假设数字始终为零填充,因此它们的长度相同。如果没有,那么就会面临更大的麻烦。
其次,假设文件名与增量编号组件完全相同。
如果这些假设为真,那么算法应该是查看第一个和最后一个文件名中的每个字符,以确定哪些相同位置的字符不匹配。
var start = String.Empty;
var end = String.Empty;
for (var index = 0; index < firstFile.Length; index++)
{
char c = firstFile[index];
if (filenames.Any(filename => filename[index] != c))
{
start += firstFile[index];
end += lastFile[index];
}
}
// convert to int if required
编辑:更改为检查每个文件名,直到找到差异。虽然效率不高,但非常简单明了。
答案 2 :(得分:1)
使用正则表达式解析文件名中的数字:
^.+\w(\d+)[^\d]*$
从这些解析后的字符串中,找到最大长度,并用零填充小于最大长度的任何长度。
按字母顺序对这些填充的字符串进行排序。从这个排序列表中取出第一个和最后一个,给你最小和最大数字。
答案 3 :(得分:0)
这是我的解决方案。它适用于您提供的所有示例,并且假定要对输入数组进行排序。
请注意,它并不仅仅是数字;它会查找可能在所有字符串中不同的一致字符序列。因此,如果你提供{"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);
}
}
}