【问题标题】:foreach over files in order of file indexes (file1.png, file2.png, file10.png) [duplicate]按文件索引的顺序遍历文件(file1.png,file2.png,file10.png)[重复]
【发布时间】:2016-02-18 05:38:03
【问题描述】:

这是我的代码:

private void Method1()
{
    int i = 1;
    foreach (string file in Directory.EnumerateFiles(ImagesPath))
    {
        if (Path.GetExtension(file).EndsWith(".png"))
        {
            string image = (Path.GetFullPath(file));
            i += 1;                
        }
    }
}

imagesPath 是一个字符串,它绑定到包含图像的文件夹,

Image1.png,
Image2.png
.
.
.
.
Image10.png,
Image11.png
.
.

我想从 Image1.png--->Image2.png 迭代,但是 foreach 迭代 Image1.png-->Image10.png-->Image11.png 等等。

有什么办法可以覆盖吗?

【问题讨论】:

  • 图片都是以“image”开头,以“.png”结尾的吗?

标签: c# foreach natural-sort


【解决方案1】:

您需要去掉“image”前缀和“.png”后缀,将剩下的转换为整数并对其进行排序。例如:

var orderedFiles = Directory
    .EnumerateFiles(ImagesPath)
    //Remove "image" and ".png" and convert the rest to an integer
    .Select(f => int.Parse(f.Replace("image", "").Replace(".png", ""))
    //Order the resultnumerically
    .OrderBy(num => num)
    //Add the "image" prefix and ".png" suffix back in
    .Select(num => string.Format("image{0}.png", num));

foreach(string file in orderedFiles)
{
    //...
}

此外,您的目录中似乎包含非 PNG 文件。不要在循环中使用if,只需在Directory.EnumerateFiles 方法中过滤结果:

Directory.EnumerateFiles(ImagesPath, "*.png")

【讨论】:

  • 使用正则表达式删除数字会更通用,并且可以让您保留名称。
  • 确实,但 OP 从未回答我提出的问题。
【解决方案2】:

这应该是一个更通用的解决方案

char[] charsToTrim = new char[]{'0','1','2','3','4','5','6','7','8','9'};

List<string> orderedFiles = 
    Directory.EnumerateFiles(ImagesPath)
    // need a copy of the string without the extension or trailing digits
    .Select(str => new { Orig = str, Name = Path.GetFileNameWithoutExtension(str) })
    // anonymous type containing original name, just the text part and just digit part
   .Select(tmp => new { Orig = tmp.Orig, Text = tmp.Name.TrimEnd(charsToTrim), 
            Digits = tmp.Name.Replace(tmp.Name.TrimEnd(charsToTrim), "") })
    // order by the text part
    .OrderBy(tmp => tmp.Text)
    // then by the string digits parsed as int (if no digits, use -1)
    .ThenBy(tmp => tmp.Digits.Any() ? int.Parse(tmp.Digits) : -1)
    // go back to original name
    .Select(tmp => tmp.Orig)
    // return as list
    .ToList();

现在你可以做

orderedFiles.Where(fl => Path.GetExtension(fl).ToLowerInvariant() == ".png")` 

获取所有的 png。

【讨论】:

  • 那行不通。它仍然会按字母顺序排列它们(即 Image1.png、Image10.png、Image2.png 等)
  • @ColinGrealy 现在应该可以解决问题了!
【解决方案3】:

你不能只使用for 循环吗?这会容易得多。像这样的:

  • 获取第一个文件的路径
  • 剥离它以进一步重用
string basic_path=first_image_path.Get_basic_path();

for(int i=0;i<how_many_images;i++){
 path_list.Add(path+i+".png");
}

【讨论】:

  • @AlexeiLevenkov 因为您可以使用索引器来获得正确的顺序,而无需使用一些丑陋的 hack
  • 您应该准确说明您要回答的问题版本。通过您的编辑,这是有道理的(我也认为它不能回答 OP 的实际需要 - 即使文件以序号保存,但它们都存在,这是非常罕见的)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
  • 2015-02-19
  • 2017-05-27
  • 2013-06-29
  • 2013-07-17
  • 2019-01-15
  • 1970-01-01
相关资源
最近更新 更多