获取子字符串 - 某些字符之前的所有内容

Posted

技术标签:

【中文标题】获取子字符串 - 某些字符之前的所有内容【英文标题】:Get Substring - everything before certain char 【发布时间】:2010-12-23 20:55:24 【问题描述】:

我正在尝试找出在字符串中 - 字符之前获取所有内容的最佳方法。下面是一些示例字符串。 - 之前的字符串长度不同,可以是任意长度

223232-1.jpg
443-2.jpg
34443553-5.jpg

所以我需要从起始索引 0 到 - 之前的值。所以子串会变成 223232、443 和 34443553

【问题讨论】:

【参考方案1】:

.Net Fiddle example

class Program

    static void Main(string[] args)
    
        Console.WriteLine("223232-1.jpg".GetUntilOrEmpty());
        Console.WriteLine("443-2.jpg".GetUntilOrEmpty());
        Console.WriteLine("34443553-5.jpg".GetUntilOrEmpty());

        Console.ReadKey();
    


static class Helper

    public static string GetUntilOrEmpty(this string text, string stopAt = "-")
    
        if (!String.IsNullOrWhiteSpace(text))
        
            int charLocation = text.IndexOf(stopAt, StringComparison.Ordinal);

            if (charLocation > 0)
            
                return text.Substring(0, charLocation);
            
        

        return String.Empty;
    

结果:

223232
443
34443553
344

34

【讨论】:

请帮他们一个忙,并添加错误检查,假设他打算用这个来做一个函数:) 谢谢我已经接近这个了,但很好奇除了这个组合之外是否有人有不同的方法来做到这一点。但是是的,这很好用,而且仍然很短。 如果你想要一个单行而不丢失正确的“未找到”检查,那么你可以这样做:string result = source.Substring(0, Math.Max(source.IndexOf('-'), 0)) 当已知字符串s 的长度严格超过n 时,可以使用s.Remove(n) 而不是s.Remove(n) @LukeH 如果 IndexOf 在您的示例中返回 -1,那么将返回一个空字符串,不是吗?【参考方案2】:
String str = "223232-1.jpg"
int index = str.IndexOf('-');
if(index > 0) 
    return str.Substring(0, index)

【讨论】:

赞成,因为我需要知道分隔符的索引 这实际上与 Fredou 给出的答案相同(目前是最佳答案),只是它省略了对未找到匹配项的情况的处理。【参考方案3】:

一种方法是将String.SubstringString.IndexOf 一起使用:

int index = str.IndexOf('-');
string sub;
if (index >= 0)

    sub = str.Substring(0, index);

else

    sub = ... // handle strings without the dash

从位置 0 开始,返回所有文本直到破折号,但不包括破折号。

【讨论】:

如果 index @NRNR:如果你这么说的话。 OP 知道业务需求,而不是你或我。【参考方案4】:

使用split 函数。

static void Main(string[] args)

    string s = "223232-1.jpg";
    Console.WriteLine(s.Split('-')[0]);
    s = "443-2.jpg";
    Console.WriteLine(s.Split('-')[0]);
    s = "34443553-5.jpg";
    Console.WriteLine(s.Split('-')[0]);

Console.ReadKey();

如果您的字符串没有-,那么您将获得整个字符串。

【讨论】:

如果你有多个连字符,你的数组中会有多个元素。 确实,James,如果您只期望一个连字符,这将是一个解决方案。我想你可以使用像跳过和聚合这样的 Linq 方法来获得你想要的东西,但是你得到的代码比已经提出的方法要多。这完全取决于您对传入数据的了解程度。 几年过去了,我刚刚意识到我承认詹姆斯的观点太快了。该问题询问如何找到某个字符之前的字符串。因此,该字符的进一步实例是无关紧要的,并且采用 [0] 将“正常工作”。当然,这仍然取决于我们对传入数据的信任程度。如果根本没有'-'怎么办? 我认为@JamesDunne 的观点是,通过拆分成一个数组,你会创建一堆不必要的字符串——不必要的垃圾。 我不会担心“不必要的垃圾”。以这种方式创建的任何额外字符串都将立即无法访问,因此在第 0 代中收集,这确实是一个极低的开销。垃圾收集器的设计明确旨在允许使用大量的短期项目而几乎没有任何费用。【参考方案5】:

自从这个话题开始以来,事情发生了一些变化。

现在,你可以使用

string.Concat(s.TakeWhile((c) => c != '-'));

【讨论】:

如何将性能与明显的 IndexOf 和 Substring 组合进行比较?我假设它将每个字符附加到 StringBuilder,然后在最后生成一个字符串。还混入了几个函数调用。如果 Substring 可以简单地将 -1 作为“长度”参数,意思是“字符串结尾”,那就太好了。 效率更差。正如你所说,它使用了一个字符串生成器,并且检查了代码似乎在每个字符上调用了 ToString 。如果您要查找多个字符,则更清楚,因为您可以轻松地重写 lambda。【参考方案6】:

以 BrainCore 的回答为基础:

    int index = 0;   
    str = "223232-1.jpg";

    //Assuming we trust str isn't null 
    if (str.Contains('-') == "true")
    
      int index = str.IndexOf('-');
    

    if(index > 0) 
        return str.Substring(0, index);
    
    else 
       return str;
    

【讨论】:

【参考方案7】:

您可以为此目的使用正则表达式,但是当输入字符串与正则表达式不匹配时,最好避免额外的异常。

首先要避免转义到正则表达式模式的额外头痛 - 我们可以为此目的使用函数:

String reStrEnding = Regex.Escape("-");

我知道这不会做任何事情 - 因为“-”与 Regex.Escape("=") == "=" 相同,但如果字符是 @"\",它会有所不同。

然后我们需要从字符串的请求匹配到字符串结尾,或者如果没有找到结尾 - 则不匹配。 (空字符串)

Regex re = new Regex("^(.*?)" + reStrEnding);

如果您的应用程序对性能至关重要 - 然后为新的 Regex 单独一行,如果不是 - 您可以将所有内容放在一行中。

最后匹配字符串并提取匹配的模式:

String matched = re.Match(str).Groups[1].ToString();

之后,您可以编写单独的函数,就像在另一个答案中所做的那样,或者编写内联 lambda 函数。我现在使用两种表示法编写 - 内联 lambda 函数(不允许默认参数)或单独的函数调用。

using System;
using System.Text.RegularExpressions;

static class Helper

    public static string GetUntilOrEmpty(this string text, string stopAt = "-")
    
        return new Regex("^(.*?)" + Regex.Escape(stopAt)).Match(text).Groups[1].Value;
    


class Program

    static void Main(string[] args)
    
        Regex re = new Regex("^(.*?)-");
        Func<String, String> untilSlash = (s) =>  return re.Match(s).Groups[1].ToString(); ;

        Console.WriteLine(untilSlash("223232-1.jpg"));
        Console.WriteLine(untilSlash("443-2.jpg"));
        Console.WriteLine(untilSlash("34443553-5.jpg"));
        Console.WriteLine(untilSlash("noEnding(will result in empty string)"));
        Console.WriteLine(untilSlash(""));
        // Throws exception: Console.WriteLine(untilSlash(null));

        Console.WriteLine("443-2.jpg".GetUntilOrEmpty());
    

顺便说一句 - 将正则表达式模式更改为 "^(.*?)(-|$)" 将允许拾取直到 "-" 模式或者如果未找到模式 - 拾取所有内容直到字符串结束。

【讨论】:

【参考方案8】:

LINQy 方式

String.Concat("223232-1.jpg".TakeWhile(c => c != '-'))

(但是,您确实需要测试 null ;)

【讨论】:

【参考方案9】:

对C#≥8的Fredou的解决方案稍作修改和刷新

使用range operator syntax (..) 使用local function 提琴手:link
/// <summary>
/// Get substring until first occurrence of given character has been found. Returns the whole string if character has not been found.
/// </summary>
public static string GetUntil(this string that, char @char)

    return that[..(IndexOf() == -1 ? that.Length : IndexOf())];
    int IndexOf() => that.IndexOf(@char);

测试:

[TestCase("", ' ', ExpectedResult = "")]
[TestCase("a", 'a', ExpectedResult = "")]
[TestCase("a", ' ', ExpectedResult = "a")]
[TestCase(" ", ' ', ExpectedResult = "")]
[TestCase("/", '/', ExpectedResult = "")]
[TestCase("223232-1.jpg", '-', ExpectedResult = "223232")]
[TestCase("443-2.jpg", '-', ExpectedResult = "443")]
[TestCase("34443553-5.jpg", '-', ExpectedResult = "34443553")]
[TestCase("34443553-5-6.jpg", '-', ExpectedResult = "34443553")]
public string GetUntil(string input, char until) => input.GetUntil(until);

【讨论】:

以上是关于获取子字符串 - 某些字符之前的所有内容的主要内容,如果未能解决你的问题,请参考以下文章

获取两个不同的开始和结束分隔符之间的所有子字符串

PHP cURL字符串获取字符串某些部分之前和之后的所有内容

如何从字符中获取子字符串

在 SQL Server 2008 中的符号之前隔离字符串中的子字符串

可重叠最长重复子串

使用javascript获取两个字符之间的子字符串