web-dev-qa-db-fra.com

C # Regex.Split: Suppression des résultats vides

Je travaille sur une application qui importe des milliers de lignes où chaque ligne a un format comme celui-ci:

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

J'utilise la variable Regex suivante pour fractionner les lignes aux données dont j'ai besoin:

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

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

Cela me donne le résultat suivant:

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

Maintenant, j'ai deux questions.
1. Comment puis-je supprimer les résultats vides? Je sais que je peux utiliser:

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

mais existe-t-il une méthode intégrée pour supprimer les résultats vides?

2. Comment puis-je retirer le dernier tuyau?

Merci pour toute aide.
Cordialement,
Yogesh.

MODIFIER:
Je pense que ma question était un peu mal comprise. Il n’a jamais été question de comment je peux le faire. Il s’agissait seulement de comment puis-je le faire en modifiant la Regex dans le code ci-dessus.

Je sais que je peux le faire de plusieurs façons. Je l'ai déjà fait avec le code mentionné ci-dessus avec une clause Where et avec un autre moyen également plus rapide (plus de deux fois):

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

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

Deuxièmement, en tant que test élémentaire, mon système peut analyser 92k + ​​de telles lignes en moins de 1,5 seconde dans la méthode d'origine et en moins de 700 millisecondes dans la seconde, où je ne trouverai jamais plus de deux mille dans des cas réels. Je ne pense pas avoir besoin de penser à la vitesse ici. À mon avis, l’optimisation prématurée est une question de vitesse.

J'ai trouvé la réponse à ma première question: cela ne peut pas être fait avec Split car aucune option de ce type n'est intégrée.

Je cherche toujours une réponse à ma deuxième question.

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

ou vous pouvez simplement faire:

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

Et non, il n'y a aucune option pour supprimer les entrées vides pour RegEx.Split telles quelles pour String.Split.

Vous pouvez également utiliser des allumettes.

40
Jaroslav Jandek

Je pense que cela peut fonctionner comme un équivalent pour supprimer des chaînes vides:

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

Au lieu de séparer, ce qui posera toujours des problèmes lorsque vos délimiteurs sont également présents au début et à la fin de l'entrée, vous pouvez essayer de faire correspondre le contenu des canaux:

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

N'utilisez pas de regex du tout dans votre cas… .. Il ne semble pas que vous en ayez besoin et les regex sont beaucoup plus lents (et ont une charge beaucoup plus lourde) que d'utiliser directement les fonctions string.

Alors utilisez un peu comme:

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

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

Sur la base de l'excellente réponse de @Jaroslav Jandek, j'ai écrit un 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. Comment puis-je supprimer les résultats vides?

Vous pouvez utiliserLINQpour supprimer toutes les entrées égales à string.Empty:

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

2. Comment puis-je retirer le dernier tuyau?

Vous pouvez utiliser LINQ ici pour supprimer toutes les entrées équivalentes au caractère que vous souhaitez supprimer:

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

utiliser cette solution:

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

Que dis-tu de ça:

en supposant que nous ayons une ligne:

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

nous pouvons avoir le résultat requis comme:

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

Cela donnera le résultat suivant:

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

J'ai peut-être une idée fausse, mais vous voulez simplement scinder la chaîne data à l'aide de '| caractère comme délimiteur? Dans ce cas, vous pourriez essayer:

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

Cela retournera tous les champs, sans espaces et avec les champs vides supprimés. Vous pouvez utiliser ce que vous voulez dans la partie Select pour formater les résultats, par exemple.

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