【问题标题】:How to compare the contents of two arrays and returning the index of the duplicated file?如何比较两个数组的内容并返回重复文件的索引?
【发布时间】:2018-08-18 21:19:04
【问题描述】:

我创建了一个方法来比较两个文件目录中的文件,如果有以布尔形式重复的文件,它会返回。但是,实际上希望它返回文件名或文件在其数组中的索引,这样我就可以删除该文件,这样在将文件移动到一个目录时就不会出现复杂情况。我尝试将“==”比较语句转换为字符串,希望它会给出文件名,但我忘记了,因为它是一个布尔运算,它只会返回 true 或 false。

static public string ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
    {
        string NoDuplicateMods = "There are no duplicate mods";
        foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
        {
            foreach (var  ModInModsDirectory in SimsModsDirectory)
            {
                if (ModInDownloadDirectory == ModInModsDirectory)
                {

                    string DuplicateMod = (ModInDownloadDirectory == ModInModsDirectory).ToString();
                    return DuplicateMod;
                }
                else
                {
                    return NoDuplicateMods;
                }
            }
        }
        return NoDuplicateMods;
    }

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    你可以通过类似这样的方式获取匹配字符串的索引

    var result = SimsModDownloadDirectory.Select((x, i) => 
                     {return (SimsModsDirectory.Contains(x) ? i :-1);})
                     .Where(x => x != -1);
    foreach(int index in result)
       Console.WriteLine(index);
    

    思路如下:
    用重载选择第一个列表中的所有字符串 (x),该重载还为我们提供了枚举字符串 (i) 的索引,如果枚举字符串包含在第二个列表中,则返回其索引,否则返回 -1。最后用 Where 只提取 Select 提取的非 -1 值

    当然,只返回重复项的名称要简单得多

    var result = SimsModDownloadDirectory.Intersect(SimsModsDirectory);
    foreach(string name in result)
       Console.WriteLine(name);
    

    这些方法基于要比较的两个字符串之间的大小写完全匹配。所以字符串“Steve”不会匹配字符串“steve”。
    如果您的要求是在比较中忽略大小写,那么您可以更改为

    var result = SimsModDownloadDirectory.Select((x, i) => 
                 {
                    return (SimsModsDirectory.Contains(x,  
                            StringComparer.CurrentCultureIgnoreCase) ? i :-1);
                 }).Where(x => x != -1);
    

    或到

    var result = SimsModDownloadDirectory.Intersect(SimsModsDirectory,  
                               StringComparer.CurrentCultureIgnoreCase);
    

    【讨论】:

      【解决方案2】:

      代码中的 else 是问题所在。

      示例代码(未经测试)

          static public string ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
      {
          string NoDuplicateMods = "There are no duplicate mods";
          foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
          {
              foreach (var  ModInModsDirectory in SimsModsDirectory)
              {
                  if (ModInDownloadDirectory == ModInModsDirectory)
                  {
                      return ModInModsDirectory;
                  }
              }
          }
          return NoDuplicateMods;
      }
      

      上面只返回第一个副本。对于所有重复项,您必须维护一个列表并在最后返回它

      static public List<string> ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
      {
          var duplicateDirs = new List<string>();
      
          foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
          {
              foreach (var  ModInModsDirectory in SimsModsDirectory)
              {
                  if (ModInDownloadDirectory == ModInModsDirectory)
                  {
                      duplicateDirs.Add(ModInModsDirectory);
                  }
              }
          }
          return duplicateDirs;
      }
      

      【讨论】:

      • OP 想要重复的文件名或索引。不知道有没有重复
      • 谢谢!现在对其进行编辑以回答 OP 的问题
      【解决方案3】:

      我不完全知道你想要达到什么目的。您的代码没有告诉我们返回值应该是什么。如果你想告诉调用者“有/没有重复的文件名”,你可以很容易地返回bool。如果要返回“重复文件名”,则应返回 string[] 或 FileInfo[] 或 IReadOnlyCollection&lt;string&gt; 或类似名称。返回集合或数组的好处是,调用者可以通过检查返回值的Length/Count 轻松查看是否有/没有任何重复项。

      使用嵌套的for 循环,性能较差,为 O(n*m)。使用HashSet或LINQ的Intersect方法,可以轻松实现O(n+m)的目标:

      public static IReadOnlyList<string> FindDuplicateModFiles(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
      {
          var set = new HashSet<string>(SimsModDownloadDirectory);
          var result = new List<string>();
          foreach (string file in SimsModsDirectory)
          {
              if (set.Contains(file))
                  result.Add(file);
          }
          return result.AsReadOnly();
      }
      

      或者使用 LINQ:

      public static IEnumerable<string> FindDuplicateModFiles2(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
      {
          return SimsModDownloadDirectory.Intersect(SimsModsDirectory);
      }
      

      如果您想从第一个集合中删除重复项,最好的选择是 LINQ 的 Except 方法:

      public static IEnumerable<string> GetNonDuplicatesInFirst(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
      {
          return SimsModDownloadDirectory.Except(SimsModsDirectory);
      }
      

      【讨论】:

      • 注意:IReadOnlyCollection&lt;T&gt; 在 .NET 4.5 及更高版本中可用。
      • 为了更清楚,我试图查看重复文件的名称,以便我可以从 SimsModDownloadDirectory 数组中删除它们,这样当我将文件传输到目录时它不会抛出异常说文件已存在。
      【解决方案4】:
          static public IEnumerable<string> ModFileDupilcate(string[] SimsModDownloadDirectory, 
             string[] SimsModsDirectory)
          {
              var result = SimsModDownloadDirectory.Select((x, i) => 
                  SimsModsDirectory.Contains(x) ? x : string.Empty).
                  Where(x => !string.IsNullOrEmpty(x));
              return result;
          }
      

      调用方法如:

          var resultOfDublicateFiles = ModFileDupilcate(SimsModDownloadDirectory,SimsModsDirectory);
      

      或者

      public static bool ModFileDupilcate(string[] SimsModDownloadDirectory, 
             List<string> SimsModsDirectory,out List<string> dublicatedFiles)
          {
              dublicatedFiles = new List<string>();
              foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
              {
                  foreach (var  ModInModsDirectory in SimsModsDirectory)
                  {
                      if (ModInDownloadDirectory == ModInModsDirectory)
                      {   
                          dublicatedFiles.Add(ModInModsDirectory);
                      }
                  }
              }
              return dublicatedFiles.Count > 0;
          }
      

      调用方法如:

      List<string> dublicatedFiles;
      bool hasDublicatedFiles= ModFileDupilcate(new string["a","b","c"],new string["b","c","d","f"],out dublicatedFiles);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-08
        • 2018-03-14
        • 1970-01-01
        • 2021-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-04
        相关资源
        最近更新 更多