【问题标题】:Getting substring between two separators in an arbitrary position在任意位置的两个分隔符之间获取子字符串
【发布时间】:2013-01-23 16:31:58
【问题描述】:

我有以下字符串:

string source = "Test/Company/Business/Department/Logs.tvs/v1";

/ 字符是字符串中各个元素之间的分隔符。我需要获取字符串的最后两个元素。为此,我有以下代码。这工作正常。有没有更快/更简单的代码?

代码

    static void Main()
    {
        string component = String.Empty;
        string version = String.Empty;
        string source = "Test/Company/Business/Department/Logs.tvs/v1";
        if (!String.IsNullOrEmpty(source))
        {
            String[] partsOfSource = source.Split('/');
            if (partsOfSource != null)
            {
                if (partsOfSource.Length > 2)
                {
                    component = partsOfSource[partsOfSource.Length - 2];
                }

                if (partsOfSource.Length > 1)
                {
                    version = partsOfSource[partsOfSource.Length - 1];
                }
            }
        }

        Console.WriteLine(component);
        Console.WriteLine(version);
        Console.Read();
    }

【问题讨论】:

    标签: c# .net regex linq


    【解决方案1】:

    为什么没有正则表达式?这个很简单:

    .*/(?<component>.*)/(?<version>.*)$
    

    您甚至可以为您的组添加标签,因此您只需:

    component = myMatch.Groups["component"];
    version = myMatch.Groups["version"];
    

    【讨论】:

    • 在这种情况下,您不能让正则表达式引擎“从右到右”匹配,这很遗憾。
    • @Rawling:同意。我想您可以先反转字符串,但这可能效率更低。实际上,我想知道当表达式具有$ 但没有^ 时,RegEx 引擎是否不可能合并这种优化。
    • ... 好的,今天我了解到您可以执行 Regex.Match(source, "/(.*?)/(.*?)$", RegexOptions.RightToLeft) 之类的操作,在这种情况下甚至可以不使用 $
    【解决方案2】:

    下面的应该更快,因为它只扫描尽可能多的字符串以找到两个/,并且不会费心拆分整个字符串:

    string component = "";
    string version = "";
    string source = "Test/Company/Business/Department/Logs.tvs/v1";
    int last = source.LastIndexOf('/');
    if (last != -1)
    {
        int penultimate = source.LastIndexOf('/', last - 1);
        version = source.Substring(last + 1);
        component = source.Substring(penultimate + 1, last - penultimate - 1);
    }
    

    也就是说,与所有性能问题一样:配置文件!将这两个与现实生活中的大量输入并排尝试,看看哪个最快。

    (另外,如果输入中有 no 斜杠,这将留下空字符串而不是抛出异常......但如果 source 为空,我就懒惰了。)

    【讨论】:

    • 这听起来像是过早的优化。拆分此字符串不太可能成为性能瓶颈。
    【解决方案3】:

    鉴于您正在寻找特定索引处的子字符串,您的方法是最合适的方法。在这种情况下执行相同操作的 LINQ 表达式可能不会提高代码或其可读性。

    作为参考,Microsoft here 提供了一些关于使用字符串和 LINQ 的重要信息。请特别参阅文章here,其中涵盖了一些使用 LINQ 和 RegEx 的示例。

    编辑:+1 对于马特在 RegEx 方法中的命名组......这是我见过的最好的解决方案。

    【讨论】:

      【解决方案4】:

      您的代码大部分看起来都不错。需要注意的几点:

      1. String.Split() 永远不会返回 null,因此您不需要对其进行 null 检查。
      2. 如果source 字符串少于两个/ 字符,您将如何处理?(原帖已更新以解决此问题)
      3. 如果源字符串为空或空(或无效),您真的只想输出空字符串吗?如果您对输入的性质有特定的期望,那么当这些期望未得到满足时,您可能需要考虑快速失败。

      【讨论】:

        【解决方案5】:

        您可以尝试这样的方法,但我怀疑它会快得多。您可以使用 System.Diagnostics.StopWatch 进行一些测量,看看您是否觉得需要。

        string source = "Test/Company/Business/Department/Logs.tvs/v1";
        
        int index1 = source.LastIndexOf('/');
        string last = source.Substring(index1 + 1);
        
        string substring = source.Substring(0, index1);
        int index2 = substring.LastIndexOf('/');
        string secondLast = substring.Substring(index2 + 1);
        

        【讨论】:

          【解决方案6】:

          我会试试的

                  string source = "Test/Company/Business/Department/Logs.tvs/v1";
          
                  var components = source.Split('/').Reverse().Take(2);
          
                  String last = string.Empty;
          
                  var enumerable = components as string[] ?? components.ToArray();
                  if (enumerable.Count() == 2)
                      last = enumerable.FirstOrDefault();
                  var secondLast = enumerable.LastOrDefault();
          

          希望这会有所帮助

          【讨论】:

          • @Lijo 编辑了我的答案,对 R# 进行了一些重构,并添加了对 components.Count
          【解决方案7】:

          您可以使用以下过程检索最后两个单词:

          string source = "Test/Company/Business/Department/Logs.tvs/v1";
          
           String[] partsOfSource = source.Split('/');
          if(partsOfSourch.length>2)
           for(int i=partsOfSourch.length-2;i<=partsOfSource.length-1;i++)
          console.writeline(partsOfSource[i]);
          

          【讨论】:

            猜你喜欢
            • 2012-04-27
            • 1970-01-01
            • 2021-04-04
            • 2016-02-10
            • 1970-01-01
            • 1970-01-01
            • 2014-12-08
            • 1970-01-01
            • 2017-03-17
            相关资源
            最近更新 更多