2009-01-07 10 views
55

Para la parte de esperanza de tener una respuesta en 30 segundos de esta pregunta, estoy buscando específicamente C#¿Cómo puedo eliminar la puntuación de una cadena?

Pero en el caso general, ¿cuál es la mejor manera de quitar la puntuación en cualquier ¿idioma?

Debo añadir: Idealmente, las soluciones no requerirán que enumere todos los posibles signos de puntuación.

relacionadas: Strip Punctuation in Python

+0

Diferentes idiomas son, de hecho, diferentes, y no creo que haya una respuesta a la pregunta que está haciendo. Puede preguntar sobre idiomas específicos, o qué idioma sería el mejor para ese tipo de manipulación. –

Respuesta

3

La forma más sencilla de hacer más braindead que estaría utilizando String.Replace

La otra forma me imagino es un regex.replace y tienen su expresión regular con toda la puntuacion adecuada marcas en ella

13

Suponiendo que "mejor" significa "más simple" Sugiero usar algo como esto:

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

Este ejemplo es para Java, pero todos los motores de expresiones regulares suficientemente modernos debe apoyar esto (o algo similar).

Editar: la versión Unicode-Aware sería la siguiente:

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

La primera versión sólo se basa en los caracteres de puntuación contenidas en ASCII.

+0

C# no tiene la clase 'Punct', pero sí' P' – JProgrammer

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

Sí. Está alimentando la operación de cadena que publiqué a continuación. –

+4

LinQ nunca deja de sorprenderme. – Dermot

+0

Brillante. Menos es más. –

8

Usted puede utilizar el método regex.replace:

replace(YourString, RegularExpressionWithPunctuationMarks, Empty String) 

Dado que este devuelve una cadena, el método se verá algo como esto:

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

Puede reemplazar "[? !] "con algo más sofisticado si lo deseas:

(\p{P}) 

Esto debería encontrar cualquier signo de puntuación.

+0

+1 para usar una clase de caracteres Unicode. Conciso, preciso y agradable. –

4

Basado de la idea de GWLlosa, yo era capaz de llegar a la suprema feo, pero trabajando:

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

Lo sé; ¿derecho? Mi pasatiempo es cometer pecados en contra del código en Linq. Pero por favor, por supuesto, hazlo mejor. –

+4

Busque ayuda psiquiátrica. –

+0

Eso es cuadrático en la longitud en s; si doblas la longitud, el código será cuatro veces más lento, porque el operador + de la cadena tiene que hacer una copia de la cadena:/ –

1

Aquí es un enfoque ligeramente diferente utilizando LINQ. Me gusta AviewAnew, pero éste evita el agregado

 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

¿Por qué el 'IEnumerable ' para organizar en bytes la conversión de cadenas, ¿por qué no simplemente 'nuevo String (s.ToArray()) '? ¿O es eso lo que la nueva cuerda hará bajo el capó de todos modos? –

17

Por qué no simplemente:

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

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

s = sb.ToString(); 

El uso de expresiones regulares es normalmente más lento que las operaciones de char simples. Y esas operaciones LINQ me parecen excesivas. Y no puede usar dicho código en .NET 2.0 ...

+0

Tenga en cuenta que este enfoque también le permite reemplazar la puntuación con (por ejemplo) espacios en blanco. Útil para tokenizar. –

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

Describe la intención, más fácil de leer (en mi humilde opinión) y de mejor rendimiento:

s = s.StripPunctuation(); 

de implementar:

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

Se trata de utilizar el algoritmo de Hades32 que era el mejor rendimiento del montón al corriente.

+0

tidbit interesante: los siguientes no son signos de puntuación: $^+ | <> = –

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

Este hilo es tan antiguo, pero sería un error no publicar una solución más elegante (IMO).

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

Es LINQ sans WTF.

0

Para cadenas largas que utilizan este:

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

rinde mucho mejor que el uso de concatenaciones de cadenas (aunque estoy de acuerdo que es menos intuitivo).

1

Me enfrenté al mismo problema y me preocupaba el impacto en el rendimiento de llamar a IsPunctuation para cada comprobación.

He encontrado este post: http://www.dotnetperls.com/char-ispunctuation.

Al otro lado de las líneas: char.IsPunctuation también maneja Unicode encima de ASCII. El método coincide con un grupo de caracteres, incluidos los de control. Por definición, este método es pesado y costoso.

La conclusión es que finalmente no fui por su impacto en el rendimiento en mi proceso de ETL.

Fui para la implementación personalizada de dotnetperls.

Y sobresalen FYI, aquí hay un código deduce de las respuestas anteriores para obtener la lista de todos los caracteres de puntuación (excluidos los de control):

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 desea para usar esto para el texto de tokenización puede usar:

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