如何从文件名列表中解析编号序列?

时间:2010-12-24 00:06:09

标签: c# parsing c#-3.0 filenames

我想从已排序的 {{1}自动解析 范围 编号序列通过检查文件名的哪一部分发生变化来修改文件名。

以下是一个示例(文件扩展名已被删除):

  

第一个文件名List<FileData>
  上次文件名IMG_0000
  我需要的编号范围IMG_10000000

除了我需要处理每种可能类型的文件命名约定,例如:

  <00> 0000 ... 9999
  20080312_0000 ... 20080312_9999
  IMG_0000 - 复制... IMG_9999 - 复制
  8er_green3_00001 .. 8er_green3_09999
  等

  • 我想要整个0-padded范围,例如1000不只是0001
  • 序列号为0填充,例如1
  • 序列号可以位于任何地方,例如0001
  • 范围可以以任何内容开始和结束,即不必以IMG_0000 - Copy开头,以1结束
  • 数字可能在序列的文件名中出现多次,例如9999

每当我为8个随机测试用例工作时,第9次测试会破坏所有内容,最后我会从头开始重新开始。

我目前一直在比较第一个和最后一个文件名(而不是遍历所有文件名):

20080312_0000

有没有人有任何聪明的想法?也许是Regex的东西?

4 个答案:

答案 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);
        }
    }
}