【问题标题】:Match first part of filepath strings匹配文件路径字符串的第一部分
【发布时间】:2011-05-03 22:22:10
【问题描述】:

我有一个简单的类,如下所示:

class Record
{
    public Record(string fp1, string fp2, string fp3)
    {
        Filepath1 = fp1;
        Filepath2 = fp2;
        Filepath3 = fp3;
    }

    public string Filepath1 { get; private set; }
    public string Filepath2 { get; private set; }
    public string Filepath3 { get; private set; }
}

这些文件路径中的每一个都非常相似(而且很长),并且只会在文件路径的最后几个字符上有所不同。

现在,我想在内存中有几千个这样的记录,并且我希望这些记录占用更少的 RAM。所以我正在想办法优化内存使用,这是我想出的一个解决方案:

class Record
{
    private string _baseFilepath;
    private string _fp1;
    private string _fp2;
    private string _fp3;
    public Record(string fp1, string fp2, string fp3)
    {
        _baseFilepath = /*get common first part of filepaths*/;
        _fp1 = /*last part of fp1*/;
        _fp2 = /*last part of fp2*/;
        _fp3 = /*last part of fp3*/;
    }

    public string Filepath1
    {
        get { return _baseFilepath + _fp1; }
    }

    public string Filepath2
    {
        get { return _baseFilepath + _fp2; }
    }

    public string Filepath3
    {
        get { return _baseFilepath + _fp3; }
    }
}

您可以看到我可以节省大量 RAM,尤其是对于只有最后几个字符不同的非常长的文件路径。问题是,有没有一种简单的方法来获取文件路径的公共第一部分?

编辑: 内存中可能有多达 700,000 条记录,并且实际的生产类还有多个文件路径。我正在努力使应用程序尽可能轻量级,同时为了简单起见,尽量保持优化非常简单。

【问题讨论】:

  • 几千条记录会占用一兆左右。您是否在严重受限的硬件上运行?
  • 这实际上取决于。这是针对服务器应用的,每个连接到服务器的用户可能会导致 4000 条记录在内存中。
  • 哦,这不是我的生产课程,只是一个例子。现实生活中会有更多的文件路径。
  • 这是一个真实的文件路径还是你只是这样命名的?如果是这样,它们是否仅在实际文件名上有所不同,并且您想拆分路径?如果这是Path.GetDirectoryName() 等的任务,可能应该使用。
  • @Marcelo 不确定。我估计有 700 个用户(希望这是一个严重的高估)

标签: c# optimization memory-management


【解决方案1】:

这样就可以了:

public static string GetCommonStart(string fp1, string fp2, string fp3)
{
    int idx = 0;
    int minLength = Math.Min(Math.Min(fp1.Length, fp2.Length), fp3.Length);
    while (idx < minLength && fp1[idx] == fp2[idx] && fp2[idx] == fp3[idx])
       idx++;
    return fp1.Substring(0, idx);
}

【讨论】:

  • 很好,我会添加一个检查以确保您不会超过最短字符串的长度。 ex c:\1.jpgc:\1.jpg.jpg 会出错。编辑,就这样。 :)
【解决方案2】:

如果此操作对您来说不是性能关键,您可以使用类似的方法:

public static class StringExtensions
{
    public static string GetCommonPrefix(string a, string b)
    {
        int commonPrefixLength = 0;
        int minimumLength = Math.Min(a.Length, b.Length);

        for (int i = 0; i < minimumLength; i++)
        {
            if (a[i] == b[i])
            {
                commonPrefixLength++;
            }
        }

        return a.Substring(0, commonPrefixLength);
    }

    public static string GetCommonPrefix(params string[] strings)
    {
        return strings.Aggregate(GetCommonPrefix);
    }
}

【讨论】:

    【解决方案3】:

    请将此视为补充答案,提供替代建议,而不是直接回答您的问题(已提供)。

    如果可能,我会在第一时间将这些文件路径分解为basesuffix,然后以这种方式传递到您的整个系统。

    这适用于

    • 您自己在系统的某个位置生成这些文件路径
    • 您正在从一组已知且有限的位置读取文件

    您只需拥有一组base 文件路径,每个Filepath 引用其中一个base 值,还包含自己的suffix 值。

    根据base 文件路径的数量以及它们的确定方式,这将显着提高内存效率。您当前的解决方案提供了最佳情况下三分之一的内存使用(每三个文件路径最好优化为一个文件路径)。在整个应用程序中以一致的方式存储此对象 (filepath) 也很有意义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      • 2019-10-18
      相关资源
      最近更新 更多