1

我有以下代码要优化。由于我希望文件很大,因此我没有使用 HashMap 来存储行,而是选择了 String 数组。我尝试用大约 500,000 的 n 测试逻辑,它运行了大约 14 分钟。我肯定想让它比这快得多,并感谢任何帮助或建议。

         public static void RemoveDuplicateEntriesinFile(string filepath)
        {
              if (filepath == null)
                    throw new ArgumentException("Please provide a valid FilePath");
              String[] lines = File.ReadAllLines(filepath);
              for (int i = 0; i < lines.Length; i++)
              {
                    for (int j = (i + 1); j < lines.Length; j++)
                    {
                          if ((lines[i] !=null) && (lines[j]!=null) && lines[i].Equals(lines[j]))
                          {//replace duplicates with null
                                lines[j] = null;
                          }
                    }
              }

              File.WriteAllLines(filepath, lines);
        }

提前致谢!

4

3 回答 3

1

“因为我希望文件很大,所以我没有使用 HashMap 来存储行,而是选择了 String 数组。”</p>

我不同意你的推理;文件越大,您从散列中获得的性能优势就越大。在您的代码中,您将每一行与所有后续行进行比较,整个文件需要 O(n²) 计算复杂度。

另一方面,如果您要使用高效的散列算法,那么每次散列查找将在 O(1) 内完成;处理整个文件的计算复杂度变为 O(n)。

尝试使用 aHashSet<string>并观察处理时间的差异:

public static void RemoveDuplicateEntriesinFile(string filepath)
{
    if (filepath == null)
        throw new ArgumentException("Please provide a valid FilePath");

    HashSet<string> hashSet = new HashSet<string>(File.ReadLines(filepath));
    File.WriteAllLines(filepath, hashSet);
}

编辑:您能否尝试以下版本的算法并检查需要多长时间?它经过优化以最大程度地减少内存消耗:

HashAlgorithm hashAlgorithm = new SHA256Managed();
HashSet<string> hashSet = new HashSet<string>();
string tempFilePath = filepath + ".tmp";

using (var fs = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write))
using (var sw = new StreamWriter(fs))
{
    foreach (string line in File.ReadLines(filepath))
    {
        byte[] lineBytes = Encoding.UTF8.GetBytes(line);
        byte[] hashBytes = hashAlgorithm.ComputeHash(lineBytes);
        string hash = Convert.ToBase64String(hashBytes);

        if (hashSet.Add(hash))
            sw.WriteLine(line);
    }
}

File.Delete(filepath);
File.Move(tempFilePath, filepath);
于 2012-05-11T18:27:30.660 回答
0

lines[j] = null;对我不起作用。File.WriteAllLines(filepath, lines);将这些行写为 "" (string.Empty)

于 2012-07-31T22:18:57.173 回答
0

您可以尝试创建一个新列表并将其添加到其中。

        public static void RemoveDuplicateEntriesinFile(string filepath)
        {
              if (filepath == null)
                    throw new ArgumentException("Please provide a valid FilePath");
              String[] lines = File.ReadAllLines(filepath);
              List<String> newLines=new List<String>()
              foreach (string s in lines)
              {
                   if (newLines.Contains(s)
                   continue;
                   newLines.add(s);
              }
              //not sure if you can do this with a list, might have to convert back to array
              File.WriteAllLines(filepath, newLines);
        }
于 2012-05-11T18:22:38.477 回答