Как я могу удалить элемент из массива в VB.NET?

Как я могу удалить элемент из массива в VB.NET?

Ответ 1

Как сказал Хайнци, массив имеет фиксированный размер. Чтобы "удалить элемент" или "изменить размер", вам нужно будет создать новый массив с нужным размером и скопировать нужные вам элементы.

Здесь код для удаления элемента из массива:

<System.Runtime.CompilerServices.Extension()> _
Function RemoveAt(Of T)(ByVal arr As T(), ByVal index As Integer) As T()
    Dim uBound = arr.GetUpperBound(0)
    Dim lBound = arr.GetLowerBound(0)
    Dim arrLen = uBound - lBound

    If index < lBound OrElse index > uBound Then
        Throw New ArgumentOutOfRangeException( _
        String.Format("Index must be from {0} to {1}.", lBound, uBound))

    Else
        'create an array 1 element less than the input array
        Dim outArr(arrLen - 1) As T
        'copy the first part of the input array
        Array.Copy(arr, 0, outArr, 0, index)
        'then copy the second part of the input array
        Array.Copy(arr, index + 1, outArr, index, uBound - index)

        Return outArr
    End If
End Function

Вы можете использовать его как таковое:

Module Module1

    Sub Main()
        Dim arr = New String() {"abc", "mno", "xyz"}
        arr.RemoveAt(1)
    End Sub
End Module

В приведенном выше коде удаляется второй элемент ("mno") [который имеет индекс 1] из массива.

Чтобы использовать метод расширения, вам нужно разрабатывать .NET 3.5 или выше. Если вы используете .NET 2.0 или 3.0, вы можете вызвать метод как таковой

arr = RemoveAt(arr, 1)

Надеюсь, это то, что вам нужно.

Update

После запуска тестов на основе комментария ToolMakerSteve, исходный код не изменяет массив, который вы хотите обновить, из-за ByVal, используемого в объявлении функции. Тем не менее, написание кода типа arr = arr.RemoveAt(1) или arr = RemoveAt(arr, 1) изменяет массив, поскольку переназначает измененный массив на оригинал.

Найдите ниже обновленный метод (подпрограмма) для удаления элемента из массива.

<System.Runtime.CompilerServices.Extension()> _
Public Sub RemoveAt(Of T)(ByRef arr As T(), ByVal index As Integer)
    Dim uBound = arr.GetUpperBound(0)
    Dim lBound = arr.GetLowerBound(0)
    Dim arrLen = uBound - lBound

    If index < lBound OrElse index > uBound Then
        Throw New ArgumentOutOfRangeException( _
        String.Format("Index must be from {0} to {1}.", lBound, uBound))

    Else
        'create an array 1 element less than the input array
        Dim outArr(arrLen - 1) As T
        'copy the first part of the input array
        Array.Copy(arr, 0, outArr, 0, index)
        'then copy the second part of the input array
        Array.Copy(arr, index + 1, outArr, index, uBound - index)

        arr = outArr
    End If
End Sub

Использование метода аналогично оригиналу, за исключением того, что на этот раз нет значения возврата, поэтому попытка назначить массив из возвращаемого значения не будет работать, потому что ничего не возвращается.

Dim arr = New String() {"abc", "mno", "xyz"}
arr.RemoveAt(1)  ' Output: {"abc", "mno"} (works on .NET 3.5 and higher)
RemoveAt(arr, 1) ' Output: {"abc", "mno"} (works on all versions of .NET fx)
arr = arr.RemoveAt(1)  'will not work; no return value
arr = RemoveAt(arr, 1) 'will not work; no return value

Примечание:

  • Я использую временный массив для процесса, потому что он делает мои намерения ясными, и это именно то, что VB.NET делает за кулисами, когда вы делаете Redim Preserve. Если вы хотите изменить массив на месте с помощью Redim Preserve, см. Ответ ToolmakerSteve.
  • Методы RemoveAt, описанные здесь, являются методами расширения. Чтобы они работали, вам нужно вставить их в Module. Методы расширения не будут работать в VB.NET, если они помещены в Class.

  • Важная Если вы будете модифицировать массив с большим количеством "удалений", настоятельно рекомендуется использовать другую структуру данных, такую ​​как List(Of T), как это было предложено другими респондентами для этого вопрос.

Ответ 2

Вы не можете. Я бы предположил, что вы поместили элементы массива в List, по крайней мере, вы можете удалить элементы. Массив можно расширить, например, используя ReDim, но вы не сможете удалить элементы массива после их создания. Вам нужно будет перестроить массив с нуля, чтобы сделать это.

Если вы можете избежать этого, не используйте здесь массивы, используйте List.

Ответ 3

Это зависит от того, что вы подразумеваете под удалением. Массив имеет фиксированный размер, поэтому удаление не имеет смысла.

Если вы хотите удалить элемент i, одним из вариантов было бы перемещать все элементы j > i по одной позиции влево (a[j - 1] = a[j] для всех j или используя Array.Copy), а затем изменить размер массива используя ReDim Preserve.

Итак, если вы не вынуждены использовать массив по внешнему ограничению, рассмотрите возможность использования структуры данных, более подходящей для добавления и удаления элементов. List <T> , например, также использует массив внутри, но сам заботится обо всех проблемах изменения размера. Для удаления элементов он использует алгоритм, упомянутый выше (без ReDim), поэтому List<T>.RemoveAt - это операция O (n).

В пространстве System.Collections.Generic существует множество разных классов коллекций, оптимизированных для разных вариантов использования. Если часто требуется удаление элементов, есть много лучших опций, чем массив (или даже List<T>).

Ответ 4

Да, вы можете удалить элемент из массива. Вот метод расширения, который перемещает элементы по мере необходимости, а затем изменяет размер массива короче:

' Remove element at index "index". Result is one element shorter.
' Similar to List.RemoveAt, but for arrays.
<System.Runtime.CompilerServices.Extension()> _
Public Sub RemoveAt(Of T)(ByRef a() As T, ByVal index As Integer)
    ' Move elements after "index" down 1 position.
    Array.Copy(a, index + 1, a, index, UBound(a) - index)
    ' Shorten by 1 element.
    ReDim Preserve a(UBound(a) - 1)
End Sub

Примеры использования (при условии, что массив начинается с индекса 0):

Dim a() As String = {"Albert", "Betty", "Carlos", "David"}
a.RemoveAt(0)    ' Remove first element => {"Betty", "Carlos", "David"}
a.RemoveAt(1)    ' Remove second element => {"Betty", "David"}
a.RemoveAt(UBound(a))    ' Remove last element => {"Betty"}

Удаление элемента First или Last является обычным явлением, поэтому для этого используются удобные процедуры (мне нравится код, который более четко отражает мое намерение):

<System.Runtime.CompilerServices.Extension()> _
Public Sub DropFirstElement(Of T)(ByRef a() As T)
    a.RemoveAt(0)
End Sub

<System.Runtime.CompilerServices.Extension()> _
Public Sub DropLastElement(Of T)(ByRef a() As T)
    a.RemoveAt(UBound(a))
End Sub

Использование:

a.DropFirstElement()
a.DropLastElement()

И как сказал Хайнци, если вы это сделаете, вместо этого используйте List (Of T), если это возможно. В списке уже есть подпрограмма "RemoveAt" и другие подпрограммы, полезные для вставки/удаления элементов.

Ответ 5

Одна строка с использованием LINQ:

Dim arr() As String = {"uno", "dos", "tres", "cuatro", "cinco"}
Dim indx As Integer = 2
arr = arr.Where(Function(item, index) index <> indx).ToArray 'arr = {"uno", "dos", "cuatro", "cinco"}

Удалить первый элемент:

arr = arr.Skip(1).ToArray

Удалить последний элемент:

arr = arr.Take(arr.length - 1).ToArray

Ответ 6

Мой любимый способ:

Imports System.Runtime.CompilerServices

<Extension()> _
Public Sub RemoveAll(Of T)(ByRef arr As T(), matching As Predicate(Of T))
    If Not IsNothing(arr) Then
        If arr.Count > 0 Then
            Dim ls As List(Of T) = arr.ToList
            ls.RemoveAll(matching)
            arr = ls.ToArray
        End If
    End If
End Sub

Затем в коде, когда мне нужно что-то удалить из массива, я могу сделать это с помощью некоторого свойства в каком-либо объекте в этом массиве, имеющем определенное значение, например:

arr.RemoveAll(Function(c) c.MasterContactID.Equals(customer.MasterContactID))

Или, если я уже знаю точный объект, который хочу удалить, я могу просто сделать:

arr.RemoveAll(function(c) c.equals(customer))

Ответ 7

Переменная i представляет индекс элемента, который вы хотите удалить:

System.Array.Clear(ArrayName, i, 1)

Ответ 8

Это может быть ленивое решение, но вы не можете просто удалить содержимое индекса, который хотите удалить, переназначив их значения до 0 или "", а затем проигнорируйте/пропустите эти пустые элементы массива вместо воссоздания и копирования массивов включено и выключено?

Ответ 9

Public Sub ArrayDelAt(ByRef x As Array, ByVal stack As Integer)
    For i = 0 To x.Length - 2
        If i >= stack Then
            x(i) = x(i + 1)
            x(x.Length-1) = Nothing
        End If
    Next
End Sub

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

Ответ 10

Похоже, это звучит сложнее, чем...

    Dim myArray As String() = TextBox1.Lines
    'First we count how many null elements there are...
    Dim Counter As Integer = 0
    For x = 0 To myArray.Count - 1
        If Len(myArray(x)) < 1 Then
            Counter += 1
        End If
    Next
    'Then we dimension an array to be the size of the last array
    'minus the amount of nulls found...
    Dim tempArr(myArray.Count - Counter) As String

    'Indexing starts at zero, so let set the stage for that...
    Counter = -1

    For x = 0 To myArray.Count - 1
        'Set the conditions for the new array as in
        'It .contains("word"), has no value, length is less than 1, ect.
        If Len(myArray(x)) > 1 Then
            Counter += 1
            'So if a value is present, we move that value over to
            'the new array.
            tempArr(Counter) = myArray(x)
        End If
    Next

Теперь вы можете назначить tempArr обратно оригиналу или что вам нужно сделать с ним, как в...

TextBox1.Lines = tempArr (теперь у вас пустое поле пустое)

Ответ 11

Если массив является строковым массивом, вы можете сделать следующее:

AlphaSplit = "a\b\c".Split("\")
MaxIndex   = AlphaSplit.GetUpperBound(0)
AlphaSplit = AlphaSplit.Where(Function(item, index) index <> MaxIndex).ToArray
AlphaJoin  = String.Join("\", PublishRouteSplit)