Wie kann ich Interpunktion von einer Zeichenfolge entfernen?

70

Für die Hoffnung, in 30 Sekunden eine Antwort auf diese Frage zu haben, suche ich speziell nach C #

Aber was ist im Allgemeinen der beste Weg, um Interpunktion in einer Sprache zu entfernen?

Ich sollte hinzufügen: Idealerweise müssen Sie für die Lösungen nicht alle möglichen Satzzeichen aufzählen.

Verwandte: Strip Interpunktion in Python

Tom Ritter
quelle
Verschiedene Sprachen sind in der Tat unterschiedlich, und ich glaube nicht, dass es eine Antwort auf die Frage gibt, die Sie stellen. Sie könnten nach bestimmten Sprachen fragen oder welche Sprache für diese Art der Manipulation am besten geeignet ist.
David Thornley

Antworten:

111
new string(myCharCollection.Where(c => !char.IsPunctuation(c)).ToArray());
GWLlosa
quelle
1
Jep. Es treibt die String-Operation an, die ich unten gepostet habe.
Tom Ritter
9
LinQ überrascht mich immer wieder.
Dermot
Brillant. Weniger ist mehr.
Saeed Neamati
funktioniert nicht mit $ oder ^, vielleicht mehr. Ich bleibe bei ^ [a-zA-Z] [a-zA-Z0-9] * $
stuartdotnet
2
für $ oder ^ u kann die !char.IsSymbol(c)Validierung verwendet werden. nur für die Aufzeichnung
Razvan Dumitru
21

Warum nicht einfach:

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

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

s = sb.ToString ();

Die Verwendung von RegEx ist normalerweise langsamer als bei einfachen Zeichenoperationen. Und diese LINQ-Operationen sehen für mich wie ein Overkill aus. Und Sie können solchen Code in .NET 2.0 nicht verwenden ...

Hades32
quelle
Beachten Sie, dass Sie mit diesem Ansatz auch die Interpunktion durch (zum Beispiel) Leerzeichen ersetzen können. Nützlich zum Tokenisieren.
14

Angenommen, "am besten" bedeutet "am einfachsten", schlage ich vor, Folgendes zu verwenden:

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

Dieses Beispiel ist für Java, aber alle ausreichend modernen Regex-Engines sollten dies (oder ähnliches) unterstützen.

Bearbeiten: Die Unicode-Aware-Version wäre folgende:

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

In der ersten Version werden nur in ASCII enthaltene Satzzeichen behandelt.

Joachim Sauer
quelle
1
C # hat nicht die PunctKlasse, aber es hatP
JProgrammer
14

Beschreibt die Absicht, die am einfachsten zu lesen ist (IMHO) und die beste Leistung:

 s = s.StripPunctuation();

implementieren:

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

Hierbei wird der Algorithmus von Hades32 verwendet, der die beste Leistung der veröffentlichten Gruppe erbrachte.

Brian Low
quelle
interessanter Leckerbissen: Die folgenden sind keine Interpunktion: $ ^ + | <> =
Brian Low
9

Sie können die Methode regex.replace verwenden:

 replace(YourString, RegularExpressionWithPunctuationMarks, Empty String)

Da dies eine Zeichenfolge zurückgibt, sieht Ihre Methode ungefähr so ​​aus:

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

Sie können "[?!]" Durch etwas Anspruchsvolleres ersetzen, wenn Sie möchten:

(\p{P})

Dies sollte keine Interpunktion finden.

Anton
quelle
+1 für die Verwendung einer Unicode-Zeichenklasse. Prägnant, präzise und nett.
Tom Anderson
6

Dieser Thread ist so alt, aber ich würde es ablehnen, keine elegantere (IMO) Lösung zu veröffentlichen.

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

Es ist LINQ ohne WTF.

Nick Vaccaro
quelle
4

Basierend auf GWLlosas Idee konnte ich mir das höchst hässliche, aber funktionierende einfallen lassen:

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; }));
Tom Ritter
quelle
2
Ich weiß; Recht? Mein Hobby ist es, in Linq Sünden gegen Code zu begehen. Aber bitte machen Sie es auf jeden Fall besser.
Tom Ritter
4
Bitte suchen Sie psychiatrische Hilfe.
Tom Anderson
Das ist quadratisch in der Länge in s; Wenn Sie die Länge verdoppeln, ist der Code viermal langsamer, da der Operator + für Zeichenfolge eine Kopie der Zeichenfolge
Clément
3

Die einfachste Art, dies zu tun, wäre die Verwendung von string.replace

Der andere Weg, den ich mir vorstellen würde, ist ein regulärer Ausdruck. Ersetzen Sie Ihren regulären Ausdruck mit allen entsprechenden Satzzeichen.

TheTXI
quelle
2

Hier ist ein etwas anderer Ansatz mit linq. Ich mag AviewAnew's, aber das vermeidet das Aggregat

        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);
JoshBerke
quelle
Warum die IEnumerable<char>Konvertierung von Array in Bytes in Zeichenfolge, warum nicht einfach new String(s.ToArray())? Oder ist es das, was eine neue Saite unter der Haube tun wird?
Chris Marisic
2

Wenn Sie dies zum Tokenisieren von Text verwenden möchten, können Sie Folgendes verwenden:

new string(myText.Select(c => char.IsPunctuation(c) ? ' ' : c).ToArray())
Chris Marisic
quelle
2

Für alle, die dies über RegEx tun möchten:

Dieser Code zeigt den vollständigen RegEx-Ersetzungsprozess und gibt einen Beispiel-Regex an, der nur Buchstaben, Zahlen und Leerzeichen in einer Zeichenfolge enthält und ALLE anderen Zeichen durch eine leere Zeichenfolge ersetzt:

//Regex to remove all non-alphanumeric characters
System.Text.RegularExpressions.Regex TitleRegex = new 
System.Text.RegularExpressions.Regex("[^a-z0-9 ]+", 
System.Text.RegularExpressions.RegexOptions.IgnoreCase);

string ParsedString = TitleRegex.Replace(stringToParse, String.Empty);

return ParsedString;
S. Justin Gengo
quelle
1
$newstr=ereg_replace("[[:punct:]]",'',$oldstr);
Ash Youssef
quelle
1

Ich hatte das gleiche Problem und war besorgt über die Auswirkungen des Aufrufs der IsPunctuation für jede einzelne Prüfung auf die Leistung.

Ich habe diesen Beitrag gefunden: http://www.dotnetperls.com/char-ispunctuation .

Über die Zeilen hinweg: char.IsPunctuation verarbeitet auch Unicode über ASCII. Die Methode entspricht einer Reihe von Zeichen, einschließlich Steuerzeichen. Diese Methode ist definitiv schwer und teuer.

Das Fazit ist, dass ich mich wegen der Auswirkungen auf die Leistung meines ETL-Prozesses letztendlich nicht dafür entschieden habe.

Ich habe mich für die benutzerdefinierte Implementierung von Dotnetperls entschieden.

Und zu Ihrer Information, hier ist ein Code, der aus den vorherigen Antworten abgeleitet wurde, um die Liste aller Satzzeichen (mit Ausnahme der Kontrollzeichen) zu erhalten:

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

Prost, Andrew

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

    int main(int a, char* b[]){
    string strOne = "H,e.l/l!o W#o@r^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

quelle
0

Für lange Saiten verwende ich Folgendes:

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

Es ist viel besser als die Verwendung von String-Verkettungen (obwohl ich der Meinung bin, dass es weniger intuitiv ist).

Shay Ben-Sasson
quelle