サブストリングを取得-特定の文字の前のすべて


124

文字列内の文字-の前にすべてを取得するための最良の方法を見つけようとしています。文字列の例を以下に示します。前の文字列の長さ-変化し、任意の長さにすることができます

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

ですから、開始インデックス0から-の直前までの値が必要です。したがって、部分文字列は223232、443、および34443553になります。

回答:


144

.Net Fiddleの例

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

2
彼らに好意を示し、エラーチェックを追加してください。彼がこれから機能を作成する予定であると想定してください:)
Josh

おかげで私はこれに近かったが、誰かがこのコンボ以外にそれを行う別の方法を持っているかどうか知りたいと思った。しかし、これはうまく機能し、まだかなり短いです。
PositiveGuy

14
あなたは正しい失うことなく、ワンライナーを望んでいた場合は、「見つからない」あなたはこのような何かを行うことができ、その後のチェック:string result = source.Substring(0, Math.Max(source.IndexOf('-'), 0))
LukeH

2
文字列の長さが厳密にを超えていることがわかっている場合(ここなど)、代わりにs.Substring(0, n)を使用できます。s.Remove(n)sn
Jeppe Stig Nielsen

@LukeH例でIndexOfが-1を返す場合、空の文字列が返されますね。
クラッシュ

124

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

文字列にがない場合は、文字列-全体を取得します。


4
また、ハイフンが複数ある場合は、配列に複数の要素が含まれます。
James Dunne

2
確かに、ジェームズ、これは、単一のハイフンしか期待していない場合にのみ解決策となります。スキップや集約などのLinqメソッドを使用して必要なものを取得できると思いますが、その場合、すでに提案されているメソッドよりも多くのコードが得られます。それはすべて、受信データについてどれだけ知っているかに依存します。
Dominic Cronin

7
そして数年後、私はジェームズの主張を認めるには速すぎるということに気づきました。質問は、特定の文字の前の文字列を見つける方法を尋ねます。したがって、そのキャラクターのそれ以上のインスタンスは無関係であり、[0]を取ることは「うまくいく」でしょう。もちろん、それはまだ着信データをどれだけ信頼しているかに依存します。「-」がまったくない場合はどうなりますか?
ドミニククローニン

1
@JamesDunneのポイントは、配列に分割することで、不要な文字列(不要なガベージ)の束を作成していることだと思います。
ときめき

1
「不要なゴミ」は気になりません。この方法で作成された余分な文字列はすぐに到達できないため、世代0で収集されます。これは、オーバーヘッドが非常に低いことです。ガベージコレクターの設計は、ほとんど費用をかけずに多数の短期間のアイテムを使用できるようにすることを明示的に意図しています。
ドミニククロニン

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

セパレータのインデックスを知る必要があるため、賛成票を投じます
ピエロアルベルト

3
これは、一致が見つからない場合の処理​​を省略していることを除いて、Fredouが実際に回答したものと同じです(現在はトップの回答です)。
Dominic Cronin 2016年

7

このスレッドが始まってから、状況は少し変わってきました。

今、あなたは使うことができました

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

これは、パフォーマンスを賢明なIndexOfとSubstringの組み合わせとどのように比較しますか?StringBuilderに各文字を追加し、最後に文字列を生成することを想定しています。また、いくつかの関数呼び出しが混在しています。Substringが-1を「文字列の終わり」を意味する「長さ」引数として単純に受け取れるとしたら良かったでしょう。
クラッシュ

1
効率的には悪いです。あなたが言うように、それは文字列ビルダーを使用し、コードを検査すると、各文字でToStringを呼び出すように見えます。ラムダを簡単に書き換えることができるため、複数の文字を探している場合はより明確になります。
Anthony Wieser 2015年

4

これを行う1つの方法は、とString.Substring一緒に使用することString.IndexOfです。

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

位置0から始めて、ダッシュまでの(ダッシュを含まない)すべてのテキストを返します。


インデックス<= 0の場合は、string.emptyを返すだけです。
返金不可返品不可

5
@NRNR:そう言うなら。OPは、ビジネス要件ではなく、あなたやI.知っている
マイケルPetrotta

0

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

0

この目的で正規表現を使用できますが、入力文字列が正規表現と一致しない場合は、余分な例外を回避することをお勧めします。

まず、正規表現パターンにエスケープするという余分な頭痛を避けるために、その目的のために関数を使用することができます。

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

これは何もしないことを知っています。「-」はと同じですが、Regex.Escape("=") == "="たとえば文字が@"\"ます。

次に、文字列の先頭から文字列の末尾まで、または末尾が見つからない場合は代わりに何も一致しないように照合する必要があります。(空の文字列)

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

アプリケーションのパフォーマンスが重要な場合-新しいRegexの場合は別の行に、そうでない場合は-すべてを1行に収めることができます。

そして最後に文字列と照合し、一致したパターンを抽出します。

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

その後、別の回答で行ったように別の関数を書くか、インラインラムダ関数を書くことができます。ここでは、インラインラムダ関数(デフォルトのパラメーターを許可しない)または個別の関数呼び出しの両方の表記を使用して記述しました。

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

ところで-正規表現パターンをに変更する"^(.*?)(-|$)"と、"-"パターンまで、またはパターンが見つからなかった場合にピックアップできます-文字列の最後まですべてをピックアップします。


0

LINQyの方法

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

(ただし、nullをテストする必要があります;)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.