在所有空格处拆分字符串

时间:2009-10-13 21:23:11

标签: .net vb.net

我需要在所有空格中分割一个字符串,它应该只包含单词本身。

我怎么能在vb.net中这样做?

标签,换行符等必须全部拆分!

这已经困扰了我很长一段时间了,因为我的语法高亮显示完全忽略了除第一行之外的每一行中的第一个单词。

7 个答案:

答案 0 :(得分:23)

String.Split()(无参数)会在所有空格上拆分(包括LF / CR)

答案 1 :(得分:18)

试试这个:

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

答案 2 :(得分:5)

如果你想避免正则表达式,你可以这样做:

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

Visual Basic等价物:

"Lorem ipsum dolor sit amet, consectetur adipiscing elit" _
    .Split() _
    .Where(Function(X$) X <> String.Empty)

Where()非常重要,因为如果您的字符串彼此相邻有多个空格字符,则会删除Split()生成的空字符串。

在撰写本文时,当前接受的答案(https://stackoverflow.com/a/1563000/49241)未将此考虑在内。

答案 3 :(得分:2)

String.Split()将在每个空格上分割,因此结果通常包含空字符串。 Ruben Farias给出的正则表达式解决方案是正确的方法。我赞成了他的答案,但我想补充一点,解剖正则表达式:

\s是一个匹配所有空白字符的character class

为了在单词之间包含多个空格字符时正确分割字符串,我们需要在规范中添加quantifier(或重复运算符)以匹配单词之间的所有空格。在这种情况下使用的正确量词是+,表示给定规范的“一个或多个”出现。虽然语法"\s+"在这里已足够,但我更喜欢更明确的“[\s]+”。

答案 4 :(得分:1)

因此,在看到Adam Ralph的帖子之后,我怀疑他的解决方案比正则表达式更快。我以为我会分享我的测试结果,因为我发现它更快。

实际上有两个因素在起作用(忽略系统变量):提取的子字符串数(由分隔符数决定)和总字符串长度。下面绘制的非常简单的场景使用“A”作为由两个空格字符(空格后跟制表符)分隔的子字符串。这突出了提取的子串数量的影响。我继续进行了一些多变量测试,以得出我操作系统的以下通用方程式。

<强>正则表达式()
t =(28.33 * SSL + 572)(SSN / 10 ^ 6)

<强>分割()在哪里()
t =(6.23 * SSL + 250)(SSN / 10 ^ 6)

其中t是执行时间(以毫秒为单位),SSL是平均子字符串长度,SSN是以字符串分隔的子字符串数。

这些方程式也可以写成

t =(28.33 * SL + 572 * SSN)/ 10 ^ 6

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

其中SL是总字符串长度(SL = SSL * SSN)

结论: Split()。Where()解决方案比Regex()更快。主要因素是子字符串的数量,而字符串长度起着次要作用。相应系数的性能提升约为2倍和5倍。

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

答案 5 :(得分:1)

我发现我使用了Adam Ralph所提到的解决方案,以及P57下面的VB.NET评论,但有一个奇怪的例外。 我发现我必须在最后添加.ToList.ToArray。

像这样:

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

如果没有这个,我不断得到&#34; 无法投射类型&#39; WhereArrayIterator`1 [System.String]&#39;输入&#39; System.String []&#39;。&#34;

答案 6 :(得分:-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) })