如何在VB.NET?
中删除数组中的项目答案 0 :(得分:13)
正如海因兹所说,阵列具有固定的大小。为了“删除项目”或“调整大小”,您必须创建一个具有所需大小的新数组,并根据需要复制所需的项目。
以下是从数组中删除项目的代码:
<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)
我希望这是你需要的。
在运行基于ToolMakerSteve's comment的测试后,由于函数声明中使用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
注意:
Redim Preserve
后在幕后所做的事情。如果您想使用Redim Preserve
就地修改数组,请参阅ToolmakerSteve's answer。此处编写的RemoveAt
方法是扩展方法。要使它们正常工作,您必须将它们粘贴到 Module
中。如果将扩展方法放在Class
中,则扩展方法在VB.NET中不起作用。
重要如果您要修改包含大量“删除”的数组,强烈建议您使用其他回答者建议的其他数据结构,例如List(Of T)
这个问题。
答案 1 :(得分:11)
你做不到。我建议您将数组元素放入List
,至少可以删除项目。可以扩展数组,例如使用ReDim
,但是一旦创建了数组元素,就无法删除它们。你必须从头开始重建数组才能做到这一点。
如果可以避免,请不要在此处使用数组,请使用List
。
答案 2 :(得分: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
答案 3 :(得分:4)
这取决于 delete 的含义。数组具有固定的大小,因此删除实际上没有意义。
如果你想删除元素i
,一个选项是将所有元素j > i
向左移动一个位置(a[j - 1] = a[j]
用于所有j
,或者使用{ {1}})然后使用ReDim Preserve调整数组大小。
因此,除非您被某些外部约束强制使用数组,否则请考虑使用更适合添加和删除项的数据结构。例如,List<T>也在内部使用数组,但是它自己处理所有调整大小问题:对于删除项目,它使用上面提到的算法(没有ReDim),这就是为什么List<T>.RemoveAt
is an O(n) operation。< / p>
System.Collections.Generic命名空间中有很多不同的集合类,针对不同的用例进行了优化。如果需要经常删除项目,则有许多比数组更好的选项(甚至Array.Copy
)。
答案 4 :(得分: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),如果可能的话。 List已经有“RemoveAt”子例程,以及其他用于插入/删除元素的例程。
答案 5 :(得分:3)
我最喜欢的方式:
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))
答案 6 :(得分:2)
变量i
表示要删除的元素的索引:
System.Array.Clear(ArrayName, i, 1)
答案 7 :(得分:1)
这可能是一个懒人的解决方案,但你不能通过重新分配它们的值为0或“”来删除你想要删除的索引的内容然后忽略/跳过这些空数组元素而不是重新创建和复制数组打开和关闭?
答案 8 :(得分:1)
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
试试这个
答案 9 :(得分:0)
似乎这听起来比它更复杂......
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's 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(您现在有一个空白行的文本框)
答案 10 :(得分:0)
如果该数组是字符串数组,则可以执行以下操作:
AlphaSplit = "a\b\c".Split("\")
MaxIndex = AlphaSplit.GetUpperBound(0)
AlphaSplit = AlphaSplit.Where(Function(item, index) index <> MaxIndex).ToArray
AlphaJoin = String.Join("\", PublishRouteSplit)