web-dev-qa-db-ja.com

C#Regex.Split:空の結果の削除

私は数千行をインポートするアプリケーションに取り組んでいます。すべての行は次のような形式です。

|* 9070183020  |04.02.2011    |107222     |M/S SUNNY MEDICOS                  |GHAZIABAD                          |      32,768.00 |

次のRegexを使用して、行を必要なデータに分割しています。

Regex lineSplitter = new Regex(@"(?:^\|\*|\|)\s*(.*?)\s+(?=\|)");
string[] columns = lineSplitter.Split(data);

foreach (string c in columns)
    Console.Write("[" + c + "] ");

これは私に次の結果を与えています:

[] [9070183020] [] [04.02.2011] [] [107222] [] [M/S SUNNY MEDICOS] [] [GHAZIABAD] [] [32,768.00] [|]

さて、2つの質問があります。
1。空の結果を削除するにはどうすればよいですか。使用できることはわかっています。

string[] columns = lineSplitter.Split(data).Where(s => !string.IsNullOrEmpty(s)).ToArray();

しかし、空の結果を削除するための組み込みメソッドはありますか?

2。最後のパイプを削除するにはどうすればよいですか?

ご協力ありがとうございます。
よろしく、
ヨゲシュ。

編集:
私の質問は少し誤解されていたと思います。どうやってどうやって私ができるか上記のコードのRegexを変更することでどうやってそれを行うことができますか

いろいろな方法でできることは知っています。上記のコードでWhere句を使用し、さらに(2倍以上)高速な別の方法でそれをすでに実行しました。

Regex regex = new Regex(@"(^\|\*\s*)|(\s*\|\s*)");
data = regex.Replace(data, "|");

string[] columns = data.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

第二に、テストケースとして、私のシステムは、元の方法では1.5秒未満、2番目の方法では700ミリ秒未満で92k +​​のような行を解析できます。ここで速度について考える必要はないと思います。私の意見では、この場合の速度について考えるのは時期尚早の最適化です。

最初の質問に対する答えを見つけました。そのようなオプションは組み込まれていないため、Splitでは実行できません。

私の2番目の質問に対する答えを探しています。

30
Yogesh
Regex lineSplitter = new Regex(@"[\s*\*]*\|[\s*\*]*");
var columns = lineSplitter.Split(data).Where(s => s != String.Empty);

または単に行うことができます:

string[] columns = data.Split(new char[] {'|'}, StringSplitOptions.RemoveEmptyEntries);
foreach (string c in columns) this.textBox1.Text += "[" + c.Trim(' ', '*') + "] " + "\r\n";

そして、いいえ、RegEx.Splitの空のエントリをString.Splitのように削除するオプションはありません。

マッチを使用することもできます。

43
Jaroslav Jandek

これは空の文字列を削除するのと同じように機能するかもしれません:

string[] splitter = Regex.Split(textvalue,@"\s").Where(s => s != String.Empty).ToArray<string>();
2
Peter

区切りの代わりに、区切り文字が入力の最初と最後にも存在する場合は常に問題が発生するため、パイプ内のコンテンツを一致させることができます。

foreach (var token in Regex.Matches(input, @"\|\*?\s*(\S[^|]*?)\s*(?=\|)"))
{
    Console.WriteLine("[{0}]", token.Groups[1].Value);
}

// Prints the following:
// [9070183020]
// [04.02.2011]
// [107222]
// [M/S SUNNY MEDICOS]
// [GHAZIABAD]
// [32,768.00]
1
Quick Joe Smith

あなたの場合、正規表現を使用しないでください。文字列関数を直接使用するよりも、正規表現が必要で、正規表現がはるかに遅い(そしてオーバーヘッドがはるかに高い)ようです。

したがって、次のように使用します。

const Char[] splitChars = new Char[] {'|'};

string[] splitData = data.Split(splitChars, StringSplitOptions.RemoveEmptyEntries)
1
Foxfire

@Jaroslav Jandekの素晴らしい答えに基づいて、私はextension method、私はそれをここに入れました、おそらくそれはあなたの時間を節約することができます。

/// <summary>
/// String.Split with RemoveEmptyEntries option for clean up empty entries from result
/// </summary>
/// <param name="s">Value to parse</param>
/// <param name="separator">The separator</param>
/// <param name="index">Hint: pass -1 to get Last item</param>
/// <param name="wholeResult">Get array of split value</param>
/// <returns></returns>
public static object CleanSplit(this string s, char separator, int index, bool wholeResult = false)
{
    if (string.IsNullOrWhiteSpace(s)) return "";

    var split = s.Split(new char[] { separator }, StringSplitOptions.RemoveEmptyEntries);

    if (wholeResult) return split;

    if (index == -1) return split.Last();

    if (split[index] != null) return split[index];

    return "";
}
0
Mehdi Dehghani

1。空の結果を削除するにはどうすればよいですか?

[〜#〜] linq [〜#〜]を使用して、string.Emptyに等しいすべてのエントリを削除できます:

string[] columns = lineSplitter.Split(data); 
columns = columns.ToList().RemoveAll(c => c.Equals(string.Empty)).ToArray();

2。最後のパイプを削除するにはどうすればよいですか?

ここでLINQを使用して、削除する文字に等しいすべてのエントリを削除できます。

columns = columns.ToList().RemoveAll(c => c.Equals("|")).ToArray();
0
CBinet

このソリューションを使用してください:

string stringwithDelemeterNoEmptyValues= string.Join(",", stringwithDelemeterWithEmptyValues.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
0
Ghadir Farzaneh

これはどう:

次の行があると仮定します。

line1="|* 9070183020  |04.02.2011    |107222     |M/S SUNNY MEDICOS                  |GHAZIABAD                          |      32,768.00 |";

次のような必要な結果が得られます。

string[] columns =Regex.Split(line1,"|");
foreach (string c in columns)
         c=c.Replace("*","").Trim();

これにより、次の結果が得られます。

[9070183020] [04.02.2011] [107222] [M/S SUNNY MEDICOS] [GHAZIABAD] [32,768.00]
0
Ankush Roy

私はここで間違った考えを持っているかもしれませんが、 '|'を使用してdata文字列を分割したいだけです区切り文字としての文字?その場合、次のことを試すことができます。

string[] result = data.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries).Select(d => d.Trim()).ToArray();

これは、スペースなしで空のフィールドが削除された、すべてのフィールドを返します。 Selectの部分で好きなようにして、結果をフォーマットすることができます。

.Select(d => "[" + d.Trim() + "]").ToArray();
0
Jason Evans