Bas
Bas

Reputation: 607

Remove last element from array

How to remove the last element from an array in VB.NET. I need to split the street and housenumber.

STREET

  1. Split the address on spaces
  2. Remove last element (missing in the code)
  3. Join array

NUMBER

  1. Split the address on spaces
  2. get last element

My code:

'split address
Dim addressArray() As String = args.Content.Split(" ")

'remove last element and return the joined array
Return String.Join(" ", addressArray.Remove(addressArray.Length() - 1))

Upvotes: 5

Views: 19868

Answers (4)

Mark Hall
Mark Hall

Reputation: 54532

You could also try using Redim Preserve. These statements are carry overs from the Visual Basic 6.0 days and are not considered the .NET way of doing things, but it is another option. There may be performance issues though according to this article.

Redim Preserve addressArray(addressArray.Length - 1)

Actually to delete the last item of array you would have to:

 Redim Preserve addressArray(addressArray.Length - 2)

since they are zero based and the length is one based.

Upvotes: 6

Guffa
Guffa

Reputation: 700352

You can't remove items from an array. The size of an array is decided when you create it, and can't be changed.

You can create a result that contains the items from the array except the last one:

Return String.Join(" ", addressArray.Take(addressArray.Length() - 1))

Edit:

If you are concerned about performance, you should not do any Split or Join at all, but simply get the parts of the string using simple string operations:

Dim pos As Integer = args.Content.LastIndexOf(" "C)
Dim street As String = args.Content.Substring(0, pos)
Dim number As String = args.Content.Substring(pos + 1)

This is at least ten times faster than any other method presented here.

Edit 2:

Here is the performance test code (C#):

Dim time As Performance = New Performance(1000000, 6)

Dim address As String = "aölskdjf öawe öofij 42"

Console.WriteLine(time.Take("SplitTakeJoin", Sub()
  Dim parts As String() = address.Split(" "c)
  Dim street As String = String.Join(" ", parts.Take(parts.Length - 1))
End Sub))
Console.WriteLine(time.Take("SplitResizeJoin", Sub()
  Dim parts As String() = address.Split(" "c)
  Array.Resize(parts, parts.Length - 1)
  Dim street As String = String.Join(" ", parts)
End Sub))
Console.WriteLine(time.Take("Substring", Sub()
  Dim street As String = address.Substring(0, address.LastIndexOf(" "c))
End Sub))

Output:

SplitTakeJoin 0,000511 ms.
SplitResizeJoin 0,000323 ms.
Substring 0,000031 ms.

using this performance test class:

Public Class Performance

  Private _iterations As Integer
  Private _displayDigits As Integer
  Private _emptyTime As TimeSpan

  Public Sub New(ByVal iterations As Integer, ByVal displayDigits As Integer)
    _iterations = iterations
    _displayDigits = displayDigits
    _emptyTime = TimeSpan.Zero
    _emptyTime = Take(Sub()
      End Sub)
  End Sub

  Private Function Take(ByVal action As Action) As TimeSpan
    Dim w As Stopwatch = Stopwatch.StartNew()
    For i As Integer = 0 To _iterations - 1 Step 10
      Action()
      Action()
      Action()
      Action()
      Action()
      Action()
      Action()
      Action()
      Action()
      Action()
    Next
    w.Stop()
    Return w.Elapsed - _emptyTime
  End Function

  Public Function Take(ByVal title As String, ByVal action As Action) As String
    Dim Time As TimeSpan = Take(action)
    Return title + " " + (Time.TotalMilliseconds / Convert.ToDouble(_iterations)).ToString("N" + _displayDigits.ToString()) + " ms."
  End Function

End Class

Upvotes: 5

dbasnett
dbasnett

Reputation: 11773

    Dim foo() As String = "This is a test".Split(New Char() {" "c}, StringSplitOptions.RemoveEmptyEntries)
    Array.Resize(foo, foo.Length - 1)
    Dim s As String = String.Join(" ", foo)

or use lists

    Dim foo As New List(Of String)
    foo.AddRange("This is a test".Split(New Char() {" "c}, StringSplitOptions.RemoveEmptyEntries))
    foo.RemoveAt(foo.Count - 1)
    Dim s As String = String.Join(" ", foo)

As far as using LINQ and performance, judge for yourself

Public Class Form1

    'to LINQ or not to LINQ
    'judge for yourself

    Dim stpw As New Stopwatch

    Private Sub Button1_Click(sender As System.Object, _
                              e As System.EventArgs) Handles Button1.Click

        Dim ipsumA() As String = New String() {"Lorem", "ipsum", "dolor", "sit", _
                                               "amet", "consectetur", "adipisicing", _
                                               "elit", "sed", "do", "eiusmod", _
                                               "tempor", "incididunt", "ut", "labore", _
                                               "et", "dolore", "magna", "aliqua", "Ut", _
                                               "enim", "ad", "minim", "veniam", "quis", _
                                               "nostrud", "exercitation", "ullamco", _
                                               "laboris", "nisi", "ut", "aliquip", "ex", _
                                               "ea", "commodo", "consequat", "Duis", "aute", _
                                               "irure", "dolor", "in", "reprehenderit", "in", _
                                               "voluptate", "velit", "esse", "cillum", "dolore", _
                                               "eu", "fugiat", "nulla", "pariatur", "Excepteur", _
                                               "sint", "occaecat", "cupidatat", "non", "proident", _
                                               "sunt", "in", "culpa", "qui", "officia", "deserunt", _
                                               "mollit", "anim", "id", "est", "laborum"}

        Const tries As Integer = 100000
        Debug.WriteLine("")

        stpw.Reset()
        stpw.Start()
        For x As Integer = 1 To tries
            Dim s As String = arrayTake(ipsumA)
        Next
        stpw.Stop()
        Debug.WriteLine(stpw.ElapsedTicks.ToString)

        stpw.Reset()
        stpw.Start()
        For x As Integer = 1 To tries
            Dim s As String = arrayRsz(ipsumA)
        Next
        stpw.Stop()
        Debug.WriteLine(stpw.ElapsedTicks.ToString)

    End Sub

    Private Function arrayRsz(test As String()) As String
        Array.Resize(test, test.Length - 1)
        Return String.Join(" ", test)
    End Function

    Private Function arrayTake(test As String()) As String
        Return String.Join(" ", test.Take(test.Length - 1))
    End Function
End Class

Upvotes: 7

NoAlias
NoAlias

Reputation: 9193

This will return all but the last "word/number" in a String as an array of Strings.

Return args.content.Split(" ").Take((args.content.Split(" ").Count - 1)).ToArray()

Upvotes: 1

Related Questions