2009-10-13 2 views
15

Мне нужно разбить строку во всех пробелах, она должна ТОЛЬКО содержать сами слова.Разбиение строки во всех пробелах

Как это сделать в vb.net?

Вкладки, Newlines и т. Д. Должны быть разделены!

Это уже давно прослушивало меня, поскольку мой синтаксический ярлык я полностью игнорировал первое слово в каждой строке, за исключением самой первой строки.

+0

См. Также возможный дубликат с SplitStringOptions, чтобы удалить лишние пробелы. http://stackoverflow.com/questions/6111298/best-way-to-specify-whitespace-in-a-string-split-operation – goodeye

ответ

22

String.split() (без параметров) не делает разделить на всех пробелов (в том числе LF/CR)

+0

Почему они не включали это в качестве перегруженного LOL? Спасибо! – Cyclone

+2

, потому что он разрешает перегрузку Split (params char []) с пустым массивом. В документации для этой перегрузки упоминается такое поведение. – Jimmy

+2

ВНИМАНИЕ: Как отмечает Йоханнес Рудольф в своем ответе, если в строке есть несколько пробельных символов, String.Split будет содержать пустые элементы. Вот почему ответ Рубенса Фариаса выше. – ToolmakerSteve

18

Попробуйте это:

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

@? Что делает @? Это дает мне синтаксическую ошибку. – Cyclone

+0

Это C#. с вами все в порядке. – Jimmy

+0

Извините, это был C#; вы можете спокойно снять его –

-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

Не работает. Выглядит круто, хотя lol – Cyclone

+0

Что значит, что это не сработало? –

+0

Это просто не сработало. – Cyclone

2

String.Split() разделится на каждый пробел, так результат будет содержать пустые строки. Решение Regex, предложенное Рубеном Фариасом, является правильным способом сделать это. Я поддержал его ответ, но я хочу дать небольшое дополнение, анализируя регулярное выражение:

\s - character class, который соответствует всем пробельным символам.

Чтобы разбить строку правильно, когда она содержит несколько пробельных символов между словами, нам нужно добавить quantifier (или оператор повторения) в спецификацию, чтобы соответствовать всем пробелам между словами. В этом случае правильным квантором является +, что означает «одно или несколько» вхождений данной спецификации. Хотя синтаксиса "\s+" здесь достаточно, я предпочитаю более явный «[\s]+».

+0

Как обычно, у нас теперь есть две проблемы вместо одного ... ;-) –

3

Если вы хотите, чтобы избежать регулярных выражений, вы можете сделать это следующим образом:

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

Where() имеет большое значение, так как, если ваша строка имеет несколько пробельных символов рядом друг с другом, он удаляет пустой строки, которые будут получены из Split().

На момент написания настоящего принятого ответа (https://stackoverflow.com/a/1563000/49241) это не учитывается.

+2

отличное решение. Это не только позволяет избежать ссылки на Regex, но и быстрее (см. Мой пост ниже). Я хотел бы добавить, что я не думаю, что VB использует лямбда-оператор «=>», поэтому версия VB этого немного отличается, я думаю вот так: s.Split(). Where (Function (x) x <> String.Empty) – u8it

1

Итак, увидев пост Адама Ральфа, я подозревал его решение быть быстрее, чем решение Regex. Просто подумал, что я поделюсь результатами моего тестирования, так как нашел, что это было быстрее.


Есть действительно два фактора в игре (пренебрегая системные переменные): количество подстроки добытых (определяется по количеству разделителей), а общая длина строки. Самый простой сценарий, построенный ниже, использует «A» в качестве подстроки, разделенной двумя пробелами (пробел, за которым следует вкладка). Это подчеркивает влияние количества выделенных подстрок. Я пошел вперед и сделал несколько тестов с переменными, чтобы получить следующие общие уравнения для моей операционной системы.

Regex()
т = (28,33 * + SSL-572) (ПЛА/10^6)

Split(). Где()
т = (6.23 * SSL + 250) (SSN/10^6)

Где t - время выполнения в миллисекундах, SSL - средняя длина подстроки, а SSN - количество подстрок, разделенных строкой.

Эти уравнения можно также записать в виде

т = (28,33 * SL + 572 * ПКР)/10^6

и

т = (6.23 * SL + 250 * ПКР)/10^6

, где SL является общая длина строки (SL = SSL * ПЛА)

Вывод:. разделения() где() быстрее, чем Regex(). Основным фактором является количество подстрок, а длина строки играет второстепенную роль. Производительность составляет около 2x и 5x для соответствующих коэффициентов.


enter image description here


Вот мой код тестирования (вероятно, намного больше материала, чем это необходимо, но это установка для получения нескольких переменных данных о я говорил о)

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

Вау!Хороший анализ –

1

Я нашел, что использовал решение, как заметил Адам Ральф, плюс комментарий VB.NET ниже от P57, но с одним странным исключением. Я нашел, что мне пришлось добавить. ToList.ToArray на конце.

Как так:

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

Без этого, я постоянно получаю "Невозможно привести объект типа 'WhereArrayIterator`1 [System.String] к типу 'System.String []'."

+0

Я смог сделать эту работу прекрасной только с помощью: .Split(). Где (Функция (x) x <> String.Empty) .ToArray – Taegost

+0

Спасибо, что указали это. – Maculin

+0

Добро пожаловать. Думаю, в то время я должен был сказать, что он использовал VS2013 и .Net 4.5.2, на всякий случай это недавнее изменение. – Taegost

Смежные вопросы