2009-01-07 7 views
55

Pour l'espoir-avoir-une-réponse-dans-30 secondes partie de cette question, je suis spécifiquement C#Comment puis-je supprimer la ponctuation d'une chaîne?

Mais dans le cas général, quelle est la meilleure façon de dépouiller la ponctuation dans tout la langue?

Je devrais ajouter: Idéalement, les solutions n'exigeront pas que vous énumériez toutes les marques de ponctuation possibles.

connexes: Strip Punctuation in Python

+0

langues différentes sont, en fait, différents, et je ne pense pas qu'il y ait une réponse à la question que vous posez. Vous pouvez poser des questions sur des langues spécifiques, ou quelle langue serait la meilleure pour ce genre de manipulation. –

Répondre

3

La façon simple le plus Braindead de le faire serait d'utiliser String.replace

L'autre façon j'imagine est un Regex.Replace et votre expression régulière avec tous les signes de ponctuation appropriée marques dedans.

13

En supposant « meilleur » signifie « simple » Je suggère d'utiliser quelque chose comme ceci:

String stripped = input.replaceAll("\\p{Punct}+", ""); 

Cet exemple est pour Java, mais tous les moteurs Regex suffisamment modernes devrait soutenir ce (ou quelque chose de similaire).

Edit: la version Unicode-Aware serait ceci:

String stripped = input.replaceAll("\\p{P}+", ""); 

La première version ne porte que sur les caractères de ponctuation contenus dans ASCII.

+0

C# n'a pas la classe 'Punct' mais il a' P' – JProgrammer

85
new string(myCharCollection.Where(c => !char.IsPunctuation(c)).ToArray()); 
+0

Yup. Il alimente l'opération de chaîne que j'ai posté ci-dessous. –

+4

LinQ ne cesse jamais de m'étonner. – Dermot

+0

Brillant. Moins est plus. –

8

Vous pouvez utiliser la méthode Regex.Replace:

replace(YourString, RegularExpressionWithPunctuationMarks, Empty String) 

Depuis cette retourne une chaîne, votre méthode ressemble à quelque chose comme ceci:

string s = Regex.Replace("Hello!?!?!?!", "[?!]", ""); 

Vous pouvez remplacer « [? !] "avec quelque chose de plus sophitiqué si vous voulez:

(\p{P}) 

Ceci devrait trouver n'importe quelle ponctuation.

+0

+1 pour l'utilisation d'une classe de caractères Unicode. Concis, précis et agréable. –

4

basé au large de l'idée GWLlosa, j'ai pu venir avec le suprêmement laid, mais travailler:

string s = "cat!"; 
s = s.ToCharArray().ToList<char>() 
     .Where<char>(x => !char.IsPunctuation(x)) 
     .Aggregate<char, string>(string.Empty, new Func<string, char, string>(
      delegate(string s, char c) { return s + c; })); 
+2

Je sais; droite? Mon hobby commet des péchés contre le code à Linq. Mais s'il vous plaît, par tous les moyens, faites-le mieux. –

+4

Veuillez consulter un psychiatre. –

+0

C'est quadratique de la longueur en s; si vous doublez la longueur, le code sera quatre fois plus lent, car l'opérateur + pour chaîne doit faire une copie de la chaîne:/ –

1

est ici une approche légèrement différente en utilisant LINQ. J'aime ce AviewAnew mais évite les Aggregate

 string myStr = "Hello there..';,]';';., Get rid of Punction"; 

     var s = from ch in myStr 
       where !Char.IsPunctuation(ch) 
       select ch; 

     var bytes = UnicodeEncoding.ASCII.GetBytes(s.ToArray()); 
     var stringResult = UnicodeEncoding.ASCII.GetString(bytes); 
+0

Pourquoi le 'IEnumerable ' pour array en octets à la conversion de chaîne, pourquoi ne pas simplement 'new Chaîne (s.ToArray()) '? Ou est-ce que cette nouvelle chaîne va faire sous le capot de toute façon? –

17

Pourquoi ne pas simplement:

 
string s = "sxrdct?fvzguh,bij."; 
var sb = new StringBuilder(); 

foreach (char c in s) 
{ 
    if (!char.IsPunctuation(c)) 
     sb.Append(c); 
} 

s = sb.ToString(); 

L'utilisation de RegEx est normalement plus lent que les opérations simples char. Et ces opérations LINQ me paraissent exagérées. Et vous ne pouvez pas utiliser un tel code dans .NET 2.0 ...

+0

Notez que cette approche vous permet également de remplacer la ponctuation par (par exemple) un espace. Utile pour tokenizing. –

0
#include<string> 
    #include<cctype> 
    using namespace std; 

    int main(int a, char* b[]){ 
    string strOne = "H,e.l/l!o W#[email protected]^l&d!!!"; 
    int punct_count = 0; 

cout<<"before : "<<strOne<<endl; 
for(string::size_type ix = 0 ;ix < strOne.size();++ix) 
{ 
    if(ispunct(strOne[ix])) 
    { 
      ++punct_count; 
      strOne.erase(ix,1); 
      ix--; 
    }//if 
} 
    cout<<"after : "<<strOne<<endl; 
        return 0; 
    }//main 
9

Décrit l'intention, plus facile à lire (à mon humble avis) et le plus performant:

s = s.StripPunctuation(); 

à mettre en œuvre:

public static class StringExtension 
{ 
    public static string StripPunctuation(this string s) 
    { 
     var sb = new StringBuilder(); 
     foreach (char c in s) 
     { 
      if (!char.IsPunctuation(c)) 
       sb.Append(c); 
     } 
     return sb.ToString(); 
    } 
} 

est d'utiliser l'algorithme de Hades32 qui a été le plus performant du groupe posté.

+0

intéressant tidbit: ce qui suit ne sont pas de ponctuation: $^+ | <> = –

1
$newstr=ereg_replace("[[:punct:]]",'',$oldstr); 
6

Ce fil est si vieux, mais je voudrais de ne pas publier une solution plus élégante (OMI).

string inputSansPunc = input.Where(c => !char.IsPunctuation(c)).Aggregate("", (current, c) => current + c); 

C'est LINQ sans WTF.

0

Pour les chaînes longues j'utiliser ceci:

var normalized = input 
       .Where(c => !char.IsPunctuation(c)) 
       .Aggregate(new StringBuilder(), 
          (current, next) => current.Append(next), sb => sb.ToString()); 

plus performant que l'utilisation concaténations de chaînes (si je suis d'accord, il est moins intuitif).

1

J'ai rencontré le même problème et j'étais préoccupé par l'impact sur les performances de l'appel de la IsPunctuation pour chaque vérification. J'ai trouvé cet article: http://www.dotnetperls.com/char-ispunctuation.

Accross les lignes: char.IsPunctuation gère également Unicode au-dessus de ASCII. La méthode correspond à un groupe de caractères, y compris les caractères de contrôle. Par définition, cette méthode est lourde et coûteuse. En fin de compte, je n'ai finalement pas opté pour cela en raison de son impact sur les performances de mon processus ETL.

J'ai opté pour l'implémentation personnalisée de dotnetperls.

Et saillir Pour votre information, voici un code déduit des réponses précédentes pour obtenir la liste de tous les caractères de ponctuation (sauf ceux de contrôle):

var punctuationCharacters = new List<char>(); 

     for (int i = char.MinValue; i <= char.MaxValue; i++) 
     { 
      var character = Convert.ToChar(i); 

      if (char.IsPunctuation(character) && !char.IsControl(character)) 
      { 
       punctuationCharacters.Add(character); 
      } 
     } 

     var commaSeparatedValueOfPunctuationCharacters = string.Join("", punctuationCharacters); 

     Console.WriteLine(commaSeparatedValueOfPunctuationCharacters); 

Cheers, Andrew

1

Si vous voulez à utiliser pour le texte tokenizing vous pouvez utiliser:

new string(myText.Select(c => char.IsPunctuation(c) ? ' ' : c).ToArray()) 
Questions connexes