English 中文(简体)
Get Substring - everything before certain char
原标题:

I m trying to figure out the best way to get everything before the - character in a string. Some example strings are below. The length of the string before - varies and can be any length

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

so I need the value that s from the start index of 0 to right before -. So the substrings would turn out to be 223232, 443, and 34443553

最佳回答

.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;
    }
}

Results:

223232
443
34443553
344

34
问题回答

Use the split function.

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();
}

If your string doesn t have a - then you ll get the whole string.

String str = "223232-1.jpg"
int index = str.IndexOf( - );
if(index > 0) {
    return str.Substring(0, index)
}

Things have moved on a bit since this thread started.

Now, you could use

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

One way to do this is to use String.Substring together with String.IndexOf:

int index = str.IndexOf( - );
string sub;
if (index >= 0)
{
    sub = str.Substring(0, index);
}
else
{
    sub = ... // handle strings without the dash
}

Starting at position 0, return all text up to, but not including, the dash.

Slightly modified and refreshed Fredou s solution for C# ≥ 8

/// <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);
}

Tests:

[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);

The LINQy way

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

(But, you do need to test for null ;)

Building on BrainCore s answer:

    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;
    }

You can use regular expressions for this purpose, but it s good to avoid extra exceptions when input string mismatches against regular expression.

First to avoid extra headache of escaping to regex pattern - we could just use function for that purpose:

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

I know that this does not do anything - as "-" is the same as Regex.Escape("=") == "=", but it will make difference for example if character is @"".

Then we need to match from begging of the string to string ending, or alternately if ending is not found - then match nothing. (Empty string)

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

If your application is performance critical - then separate line for new Regex, if not - you can have everything in one line.

And finally match against string and extract matched pattern:

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

And after that you can either write separate function, like it was done in another answer, or write inline lambda function. I ve wrote now using both notations - inline lambda function (does not allow default parameter) or separate function call.

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());
    }
}

Btw - changing regex pattern to "^(.*?)(-|$)" will allow to pick up either until "-" pattern or if pattern was not found - pick up everything until end of string.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签