# Visual Basic > Visual Basic .NET > VS 2022 split by string

## StikxX

Hello, I can best split the string so that I get only the number?

ownerid 765611988751343 "User" "Test"

I just want to get the number 765611988751343

I started like this but this is how all the block are displayed to me, thanks for your help.



```
        With ListUsers
            For i As Integer = 0 To .SelectedItems.Count - 1
                Dim myString As String = ListUsers.Items(i).SubItems(0).Text
                MsgBox(myString)


                Dim strarr() As String
                strarr = myString.Split(" "c)
                For Each s As String In strarr
                    MessageBox.Show(s)
                Next
            Next
        End With
```

----------


## vbdotnut

maybe try a substring using IndexOf " "

----------


## StikxX

What do you mean by that?

----------


## vbdotnut

> What do you mean by that?


seems you are unnecessarily creating an array spit on a space when all you need is a substring

----------


## StikxX

That's right, but that's the only way to get my string 


```
Dim myString As String = ListUsers.Items(i).SubItems(0).Text
```

----------


## vbdotnut

after Text type .Substring(...)

----------


## techgnome

sigh .... split, then get just the index that you want....


```
ListUsers.Items(i).SubItems(0).Text.split(" ")(1)
```



```
        With ListUsers
            For i As Integer = 0 To .SelectedItems.Count - 1
                Dim stringYuoWant as String = ListUSers.Items(i),Subitems(0).Text.split()(1)
                MessageBox.Show(stringYouWant)
            Next
        End With
```

-tg

----------


## dday9

One alternative is to use a Regular Expression pattern to get just the numbers, for example:


```
Private Function GetFirstNumber(input As String) As String
    Dim pattern = "\d+"
    Dim matcher = New Regex(pattern)

    If (Not matcher.IsMatch(input)) Then
        Return String.Empty
    End If

    Return matcher.Match(input).Value
End Function
```

Live Demo: https://dotnetfiddle.net/OZc0UC

Doing it like this means you won't need to know the index of the number to begin with.

----------


## vbdotnut

> sigh .... split, then get just the index that you want....


This only makes sense if he going to use the other elements someplace.

----------


## dbasnett

If you have a string that is delimited by certain characters and you want to get one of the delimited elements it looks like this,



```
        Dim someText As String = "ownerid  765611988751343   User     Test"
        Dim delims() As Char = {" "c}
        Dim strSplit() As String = someText.Split(delims, StringSplitOptions.RemoveEmptyEntries)
        Dim theNumber As String = strSplit(1)
```

----------


## vbdotnut

I dont see anything in his code that requires an array, though I suppose if it gets him there then why not.

If the number is always 15 chars and always proceeded by ownerid then he need only get a substring


```
Dim MyStr As String = "ownerid 765611988751343 ""User"" ""Test"""
Dim MySubStr As String = MyStr.Substring(8, 15)
```

----------


## dday9

> I dont see anything in his code that requires an array, though I suppose if it gets him there then why not.
> 
> If the number is always 15 chars and always proceeded by ownerid then he need only get a substring


Since this is clearly an opinionated post, why is your solution of using Substring more appropriate than my suggestion of using a Regular Expression pattern?

----------


## dbasnett

> I dont see anything in his code that requires an array, though I suppose if it gets him there then why not.
> 
> If the number is always 15 chars and always proceeded by ownerid then he need only get a substring
> 
> 
> ```
> Dim MyStr As String = "ownerid 765611988751343 ""User"" ""Test"""
> Dim MySubStr As String = MyStr.Substring(8, 15)
> ```


You might be right in the two two *assumptions* but assuming is bad.  Sure I assumed that the number was the second element with a space delimiter...

----------


## vbdotnut

> Since this is clearly an opinionated post, why is your solution of using Substring more appropriate than my suggestion of using a Regular Expression pattern?


If you want my opinion, you are taking groceries out of the bag and filling cabinets and creating a procedure to get a can of beans from a cabinet when you could have gotten them right from the bag.

----------


## vbdotnut

> If you want my opinion, you are taking groceries out of the bag and filling cabinets and creating a procedure to get a can of beans from a cabinet when you could have gotten them right from the bag.


well, to be fair, this isnt really applicable to your post. I dont claim to know much about regex

----------


## vbdotnut

> You might be right in the two two assumptions but assuming is bad. Sure I assumed that the number was the second element with a space delimiter...


Im not really assuming anything. I am simply stating what makes more sense to me, and that does not include creating an unnecessary array

----------


## dbasnett

> Im not really assuming anything. I am simply stating what makes more sense to me, and that does not include creating an unnecessary array


Sure we are.  "the number is always 15 chars and always proceeded by ownerid"

You assumed that to be true but the OP didn't say that.

dday9's solution finds the first run of numbers, no delimiter needed.

----------


## Shaggy Hiker

Heck, I was assuming that the OP was just posting an example and that reality was different from the question in some way. I'm not even sure what the actual problem is? The code shown doesn't 'get' anything, it just shows a series of messageboxes (and why is MsgBox and Messagebox.Show appearing in the same code?) with an ambiguous phrase about what is being shown. 

That code looks like code written to study a problem, not code written to solve the problem in question. If that is the case, then I'd like to know more about what the user is seeing in the messagebox, at the very least, though I'd also suggest that they not use a messagebox and just put a breakpoint on the For statement and see what is in the array. 

It's all assumptions, though.

----------


## .paul.

Well if you want to argue about the best way to return one part of a delimited string...



```
Dim someText As String = "ownerid  765611988751343   User     Test"
Dim theNumber As String = someText.Split(" ", StringSplitOptions.RemoveEmptyEntries).Skip(1).Take(1).First
```

----------


## vbdotnut

> Sure we are. "the number is always 15 chars and always proceeded by ownerid"


if you read it again, you will find that I typed "If the number chars is always 15 then..."

Regex would come across as more of a professional approach, but I am sure you can agree does not match the problem, the problem is not stated in its entirety, which I would like to see how this string derives in this way to begin with. If you don't work with Regex regularly it is a simple thing to forget all of its superior functionality.

At any rate, I shall keep all this in mind when posting an otherwise simple instruction in which could be understood by the poster.

----------


## dbasnett

> if you read it again, you will find that I typed "If...


I was just pointing out that that *was* your assumption.  If it is always 8 non-numeric characters followed by 15 numeric characters then you are the winner.

Why don't we give the OP a chance to clear this mystery up?

----------


## peterst

split = mem alloc + slow
split + linqy stuff = mem alloc + more slow
regex = mem alloc + extreme slow

indexof + substring = very fast

Benchmark results:


```
|           Method |        Mean |     Error |    StdDev |   Gen0 | Allocated |
|----------------- |------------:|----------:|----------:|-------:|----------:|
|       RegExSplit | 1,269.08 ns | 24.986 ns | 38.901 ns | 0.2785 |    2344 B |
|     SplittyLinqy |   167.90 ns |  3.183 ns |  2.822 ns | 0.0467 |     392 B |
| IndexOfSubstring |    18.04 ns |  0.437 ns |  1.289 ns | 0.0067 |      56 B |
```

What vbdotnut wrote is so simple but no one wants to read it. Use IndexOf to find begin and end of the second string (the id number) and then substring to get it.

If someone is interested, this is the benchmark code (sorry for C# 11 code but that's what I got):

C# Code:
[MemoryDiagnoser(true)]
public class GetIdBench
{
    private string input =
        """ownerid 765611988751343 "User" "Test" """;
     [Benchmark]
    public void RegExSplit()
    {
        var pattern = @"\d+";
        var matcher = new Regex(pattern);
        var id = matcher.Match(input).Value;
    }
     [Benchmark]
    public void SplittyLinqy()
    {
        var id = input.Split(' ', StringSplitOptions.RemoveEmptyEntries)
            .Skip(1)
            .Take(1)
            .First();
    }
     [Benchmark]
    public void IndexOfSubstring()
    {
        var start = input.IndexOf(' ') + 1;
        var end = input.IndexOf(' ', start + 1);
        var id = input.Substring(start, end - start);
    }
}

----------


## peterst

Regex with some optimUzation (move Regex var outside the routine and create it only once) get some good improvement in terms of performance and mem allocation:


```
|              Method |        Mean |     Error |    StdDev |      Median |   Gen0 | Allocated |
|-------------------- |------------:|----------:|----------:|------------:|-------:|----------:|
|          RegExSplit | 1,304.11 ns | 25.069 ns | 65.156 ns | 1,285.51 ns | 0.2785 |    2344 B |
| RegExSplitOptimuzed |   196.93 ns |  2.984 ns |  2.645 ns |   196.65 ns | 0.0315 |     264 B |
|        SplittyLinqy |   168.22 ns |  2.810 ns |  2.629 ns |   167.91 ns | 0.0467 |     392 B |
|    IndexOfSubstring |    18.05 ns |  0.590 ns |  1.739 ns |    17.52 ns | 0.0067 |      56 B |
```

But still we are getting 10x faster code with indexof and substring... Add that if parsing such strings is performed for millions of records and you will get the idea of perf and mem optimizations.

----------


## peterst

Using Span instead of substring gives another level of performance improvement and now with zero allocation. Too sad it is still not fully usable from VB.NET.



```
|              Method |         Mean |      Error |     StdDev |   Gen0 | Allocated |
|-------------------- |-------------:|-----------:|-----------:|-------:|----------:|
|          RegExSplit | 1,243.315 ns | 24.0451 ns | 30.4094 ns | 0.2785 |    2344 B |
| RegExSplitOptimuzed |   200.115 ns |  3.7853 ns |  3.1609 ns | 0.0315 |     264 B |
|        SplittyLinqy |   166.334 ns |  3.3475 ns |  6.2048 ns | 0.0467 |     392 B |
|    IndexOfSubstring |    21.318 ns |  0.4479 ns |  0.7844 ns | 0.0067 |      56 B |
|      IndexOfSpanner |     6.863 ns |  0.0472 ns |  0.0419 ns |      - |         - |
```

And the code:

C# Code:
[Benchmark]
public void IndexOfSpanner()
{
    var start = input.IndexOf(' ') + 1;
    var end = input.IndexOf(' ', start + 1);
    var id = input.AsSpan(start, end - start);
}

----------


## dbasnett

> Regex with some optimUzation (move Regex var outside the routine and create it only once) get some good improvement in terms of performance and mem allocation:
> 
> 
> ```
> |              Method |        Mean |     Error |    StdDev |      Median |   Gen0 | Allocated |
> |-------------------- |------------:|----------:|----------:|------------:|-------:|----------:|
> |          RegExSplit | 1,304.11 ns | 25.069 ns | 65.156 ns | 1,285.51 ns | 0.2785 |    2344 B |
> | RegExSplitOptimuzed |   196.93 ns |  2.984 ns |  2.645 ns |   196.65 ns | 0.0315 |     264 B |
> |        SplittyLinqy |   168.22 ns |  2.810 ns |  2.629 ns |   167.91 ns | 0.0467 |     392 B |
> ...


The regex should be *compiled* too.

Strictly speaking vbdotnut did a substring without regard to delimiters.  If you add that to your benchmark it'll be the winner I bet.

BUT...  If there are multiple delimiters or back-to-back-to-back delimiters the fastest methods presented won't work at all. 

The only method presented that will find a run of numbers, regardless of delimiters or lack of delimiters, is the Regex method.

----------


## vbdotnut

One thing remains a certainty, we have overkilled this by a longshot. In the back of everyone's mind exists a truth that the OP is doing something wonky to get a wonky string and is trying something wonky to achieve something that can be used. I took a best guess in that the strings in his listbox are likely going to be identical with the exclusion of the id, however initially offered the indexOf method in the event it was not.

----------

