2009-10-13 39 views
15

Necesito dividir una cadena en todos los espacios en blanco, SÓLO debe contener las palabras.División de una cadena en todos los espacios en blanco

¿Cómo puedo hacer esto en vb.net?

¡Todas las pestañas, Newlines, etc. se deben dividir!

Esto me ha estado molestando desde hace bastante tiempo, ya que mi marcador de sintaxis que hice ignora por completo la primera palabra en cada línea, excepto la primera línea.

+0

Consulte también la posibilidad de duplicar con SplitStringOptions para eliminar el espacio en blanco adicional. http://stackoverflow.com/questions/6111298/best-way-to-specify-whitespace-in-a-string-split-operation – goodeye

Respuesta

22

String.split() (sin parámetros) no dividida para todos los espacios en blanco (incluyendo LF/CR)

+0

¿Por qué no incluyen eso como una sobrecarga jajaja? ¡Muchas gracias! – Cyclone

+2

porque se resuelve con la sobrecarga de Split (params char []), con una matriz vacía. La documentación para esa sobrecarga menciona este comportamiento. – Jimmy

+2

PRECAUCIÓN: como menciona Johannes Rudolph en su respuesta, si hay múltiples espacios en blanco en una fila, String.Split contendrá elementos vacíos. Es por eso que la respuesta de Rubens Farias es superior. – ToolmakerSteve

18

Prueba esto:

Regex.Split("your string here", "\s+") 
+0

@? ¿Qué hace @? Me da un error de sintaxis – Cyclone

+0

Es C#. deberías estar bien sin – Jimmy

+0

Lo siento, fue C#; puede quitarlo con seguridad –

-1
Dim words As String = "This is a list of words, with: a bit of punctuation" + _ 
          vbTab + "and a tab character." + vbNewLine 
Dim split As String() = words.Split(New [Char]() {" "c, CChar(vbTab), CChar(vbNewLine) }) 
+0

No funcionó. Se ve bien, aunque lol – Cyclone

+0

¿Qué quieres decir con que no funcionó? –

+0

Simplemente no funcionó. – Cyclone

2

String.Split() se repartirán en todos los espacios en blanco, por lo el resultado contendrá cadenas vacías por lo general. La solución Regex que Ruben Farias ha dado es la forma correcta de hacerlo. He votado a favor su respuesta, pero quiero dar una pequeña adición, diseccionando la expresión regular:

\s es un character class que coincide con todos los caracteres de espacios en blanco.

Para dividir la cadena correctamente cuando contiene múltiples espacios en blanco entre las palabras, necesitamos agregar un quantifier (u operador de repetición) a la especificación para que coincida con todos los espacios en blanco entre las palabras. El cuantificador correcto para usar en este caso es +, que significa "una o más" ocurrencias de una especificación dada. Si bien aquí es suficiente la sintaxis "\s+", prefiero el más explícito "[\s]+".

+0

Como siempre, ahora tenemos dos problemas en lugar de uno ... ;-) –

3

Si se quiere evitar expresiones regulares, puede hacerlo de esta manera:

"Lorem ipsum dolor sit amet, consectetur adipiscing elit" 
    .Split() 
    .Where(x => x != string.Empty) 

El Where() es importante ya que, si la cadena tiene varios caracteres de espacio en blanco al lado del otro, se elimina el vacío cadenas que resultarán del Split().

En el momento de redactar este documento, la respuesta actualmente aceptada (https://stackoverflow.com/a/1563000/49241) no tiene esto en cuenta.

+2

gran solución. No solo evita la necesidad de una referencia Regex, sino que también es más rápida (ver mi publicación a continuación). Me gustaría añadir que no creo que VB haga uso del operador lambda "=>", por lo que la versión VB de esto es un poco diferente, creo así: s.Split(). Where (Function (x) x <> String.Empty) – u8it

1

Entonces, después de ver la publicación de Adam Ralph, sospeché que su solución era más rápida que la solución Regex. Solo pensé en compartir los resultados de mis pruebas ya que descubrí que era más rápido.


realidad, hay dos factores en juego (ignorando las variables del sistema): número de sub-cadenas extraídas (determinado por el número de delimitadores), y la longitud total de cadena. El escenario muy simple representado a continuación utiliza "A" como la subcadena delimitada por dos espacios en blanco (un espacio seguido de una pestaña). Esto acentúa el efecto del número de subcadenas extraídas. Continué e hice algunas pruebas de variables múltiples para llegar a las siguientes ecuaciones generales para mi sistema operativo.

Regex()
t = (28,33 * SSL + 572) (SSN/10^6)

split(). Donde()
t = (6.23 * SSL + 250) (SSN/10^6)

Donde t es el tiempo de ejecución en milisegundos, SSL es la longitud promedio de la subcadena y el SSN es el número de subcadenas delimitadas en la cadena.

Estas ecuaciones pueden también escrito como

t = (28,33 * SL + 572 * SSN)/10^6

y

t = (6,23 * SL + 250 * SSN)/10^6

donde SL es la longitud total de cadena (SL = SSL * SSN)

Conclusión:. la división() cuando() la solución es más rápida que Regex(). El factor principal es el número de subcadenas, mientras que la longitud de la secuencia juega un papel menor. Las ganancias de rendimiento son aproximadamente 2x y 5x para los respectivos coeficientes.


enter image description here


Aquí está mi código de prueba (probablemente manera más material del necesario, pero es puesta a punto para obtener los datos de múltiples variables que habló)

using System; 
using System.Linq; 
using System.Diagnostics; 
using System.Text.RegularExpressions; 
using System.Windows.Forms; 
namespace ConsoleApplication1 
{ 
    class Program 
    { 
     public enum TestMethods {regex, split}; 
     [STAThread] 
     static void Main(string[] args) 
     { 
      //Compare TestMethod execution times and output result information 
      //to the console at runtime and to the clipboard at program finish (so that data is ready to paste into analysis environment) 
      #region Config_Variables 
      //Choose test method from TestMethods enumerator (regex or split) 
      TestMethods TestMethod = TestMethods.split; 
      //Configure RepetitionString 
      String RepetitionString = string.Join(" \t", Enumerable.Repeat("A",100)); 
      //Configure initial and maximum count of string repetitions (final count may not equal max) 
      int RepCountInitial = 100;int RepCountMax = 1000 * 100; 

      //Step increment to next RepCount (calculated as 20% increase from current value) 
      Func<int, int> Step = x => (int)Math.Round(x/5.0, 0); 
      //Execution count used to determine average speed (calculated to adjust down to 1 execution at long execution times) 
      Func<double, int> ExecutionCount = x => (int)(1 + Math.Round(500.0/(x + 1), 0)); 
      #endregion 

      #region NonConfig_Variables 
      string s; 
      string Results = ""; 
      string ResultInfo; 
      double ResultTime = 1; 
      #endregion 

      for (int RepCount = RepCountInitial; RepCount < RepCountMax; RepCount += Step(RepCount)) 
      { 
       s = string.Join("", Enumerable.Repeat(RepetitionString, RepCount)); 
       ResultTime = Test(s, ExecutionCount(ResultTime), TestMethod); 
       ResultInfo = ResultTime.ToString() + "\t" + RepCount.ToString() + "\t" + ExecutionCount(ResultTime).ToString() + "\t" + TestMethod.ToString(); 
       Console.WriteLine(ResultInfo); 
       Results += ResultInfo + "\r\n"; 
      } 
      Clipboard.SetText(Results); 
     } 
     public static double Test(string s, int iMax, TestMethods Method) 
     { 
      switch (Method) 
      { 
       case TestMethods.regex: 
        return Math.Round(RegexRunTime(s, iMax),2); 
       case TestMethods.split: 
        return Math.Round(SplitRunTime(s, iMax),2); 
       default: 
        return -1; 
      } 
     } 
     private static double RegexRunTime(string s, int iMax) 
     { 
      Stopwatch sw = new Stopwatch(); 
      sw.Restart(); 
      for (int i = 0; i < iMax; i++) 
      { 
       System.Collections.Generic.IEnumerable<string> ens = Regex.Split(s, @"\s+"); 
      } 
      sw.Stop(); 
      return Math.Round(sw.ElapsedMilliseconds/(double)iMax, 2); 
     } 
     private static double SplitRunTime(string s,int iMax) 
     { 
      Stopwatch sw = new Stopwatch(); 
      sw.Restart(); 
      for (int i = 0; i < iMax; i++) 
      { 
       System.Collections.Generic.IEnumerable<string> ens = s.Split().Where(x => x != string.Empty); 
      } 
      sw.Stop(); 
      return Math.Round(sw.ElapsedMilliseconds/(double)iMax, 2); 
     } 
    } 
} 
+0

¡Guau!Buen análisis –

1

Descubrí que utilicé la solución tal como lo señaló Adam Ralph, más el comentario de VB.NET que figura a continuación en P57, pero con una extraña excepción. Descubrí que tenía que agregar .ToList.ToArray al final.

así:

.Split().Where(Function(x) x <> String.Empty).ToList.ToArray 

Sin eso, seguí recibiendo "No se puede convertir objeto de tipo 'WhereArrayIterator`1 [System.String]' al tipo 'System.String []'."

+0

Pude hacer que todo funcionara bien solo con: .Split(). Dónde (Función (x) x <> String.Empty) .ToArray – Taegost

+0

Gracias por señalarlo. – Maculin

+0

De nada. Supongo que también debería haber dicho en ese momento que estaba usando VS2013 y .Net 4.5.2, por si acaso era un cambio reciente. – Taegost

Cuestiones relacionadas