This question already has answers here:
How can I delete an item from an array in VB.NET?
(12 answers)
Closed 8 years ago.
I have below variable.
Dim strValues As String() with values "1", "2", "3", "4", "5", "6", "7"
I want to delete "4" from StrValues based on the string index without knowing the string value in vb.net. How can I do this?
I'd use Linq for simplicity:
Dim strValues = {"1", "2", "3", "4", "5", "6", "7"}
strValues = strValues.Where(Function(s) s <> "4").ToArray 'Removes all instances
Better yet, use a list:
Dim strValues = {"1", "2", "3", "4", "5", "6", "7"}.ToList
strValues.Remove("4") 'Removes first instance of "4" only
If you want to do it by value at index you could do something like the following (though these will remove all instances of the value):
Dim index = 3
strValues = strValues.Where(Function(s) s <> strValues(index)).ToArray
or
strValues = strValues.Except({strValues(index)}).ToArray
To remove or skip a given index (single instance only), you could do something like this:
Dim index = 3
strValues = strValues.Take(index).Concat(strValues.Skip(index + 1)).ToArray
Dim strValues As String() = New String() {"1", "2", "3", "4"}
Dim strList As List(Of String) = strValues.ToList()
strList.Remove("4")
strValues = strList.ToArray()
Depending on what you mean by "delete", you could do a couple of things. First, if you're for a dynamically sized array, you may want to look into the ArrayList or List(of T). This class allows you to add and delete objects to an array while resizing for you if necessary. However, if you literally want to delete it from your array, you can set the value to 0 or Nothing or shift all the values in the array after it down one index.
Related
I'm trying to create 3 sublists from the main list itemlist, but I can't find any way to achieve that. I've found a solution in python when I check out this link.
Sub CreateSubList()
Dim itemlist As Variant, itemNum As Variant
Dim oSublist As Variant
itemlist = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11")
'here I was expecting to create a variable holding sublist, as in oSublist which contains Array("1", "2", "3", "4")
'Array("5", "6", "7", "8") and Array("9", "10", "11") in each loop
'and finally iterate over the list in chunk to print the result
For Each itemNum In oSublist
Debug.Print itemNum
Next itemNum
End Sub
To be specific, I'm trying to mimic this in vba:
itemlist = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]
for i in range(0, len(itemlist), 4):
chunk = itemlist[i:i + 4]
for n in chunk:
print(n)
It seems I'm very close to solve the issue.
Sub CreateSubList()
Dim itemlist As Variant, itemNum As Variant
Dim oSublist As Variant, iCol As Collection
Dim inum As Variant
Set iCol = New Collection
itemlist = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11")
For Each inum In itemlist
iCol.Add inum
If iCol.Count >= 3 Then
For Each itemNum In iCol
Debug.Print itemNum
Next itemNum
Debug.Print "---------------------"
Set iCol = Nothing
Set iCol = New Collection
End If
Next inum
End Sub
Output I'm getting:
1
2
3
---------------------
4
5
6
---------------------
7
8
9
---------------------
However, what is still unresolved is I can't capture the two items, as in 10 and 11 conditionally from the itemlist.
Option 1 - using a jagged array
CreateSubLists() returns a jagged array Array(Array(), Array(), ...) from the sliced elements of the original array.
Option Explicit
Function CreateSubLists(itemlist, count)
Dim amount, chunks, i, j, retval, a
amount = UBound(itemlist) - LBound(itemlist) + 1 'get the amount of the elements
chunks = WorksheetFunction.RoundUp(amount / count, 0) 'calculate the number of chunks (e.g. if 2.5 then 3)
ReDim retval(0 To chunks - 1) 'make the outer array
For i = 0 To UBound(retval)
'make the inner array. If the rest of the itemlist is less then chunk then get the size of the rest
ReDim a(0 To WorksheetFunction.Min(count - 1, amount - i * count - 1))
For j = 0 To UBound(a)
a(j) = itemlist(i * count + j) 'fill the inner array
Next
retval(i) = a 'place the inner array into the outer array
Next
CreateSubLists = retval 'return the jagged array
End Function
Sub Example()
Dim itemlist, chunk
itemlist = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11")
For Each chunk In CreateSubLists(itemlist, 4) ' works with any positive integer number
Debug.Print "[" & Join(chunk, ",") & "]"
Next
End Sub
Option 2 - using Collection
Function CreateSubLists2(itemlist, count) As Collection
Dim amount, chunks, i, j, a
amount = UBound(itemlist) - LBound(itemlist) + 1 'get the amount of the elements
chunks = WorksheetFunction.RoundUp(amount / count, 0) 'calculate the number of chunks (e.g. if 2.5 then 3)
Dim retval As New Collection 'make the outer collection
For i = 0 To chunks - 1
'make the inner array. If the rest of the itemlist is less then chunk then get the size of the rest
Set a = New Collection
For j = 0 To WorksheetFunction.Min(count - 1, amount - i * count - 1)
a.Add itemlist(i * count + j) 'fill the inner collection
Next
retval.Add a 'place the inner collection into the outer collection
Next
Set CreateSubLists2 = retval 'return the collection of collections
End Function
Sub Example2()
Dim itemlist, chunk, el, s
itemlist = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11")
For Each chunk In CreateSubLists2(itemlist, 4) ' works with any positive integer number
s = "["
For Each el In chunk
s = s & el & ","
Next
s = s & "]"
Debug.Print Replace(s, ",]", "]")
Next
End Sub
Prints:
[1,2,3,4]
[5,6,7,8]
[9,10,11]
I see you're using a VBA.Collection as the vessel in which to store you sublists (slices). I prefer to use the Scripting.Dictionary which can be accessed via the Tools->References menu selecting "Microsoft Scripting Runtime" (the file is location as c:\windows\system32\scrrun.dll"
I like to use the Scripting.Dictionary to arbitrarily build arrays in code because the Items method returns an array. So I can just pass this array to something like VBA.Join. Note how I use the Dictionary's count as a unique key (neat little trick), this turns it into something very similar to a Collection.
Also I have hived off the slice print logic to separate subroutine to avoid duplication. You need to call both inside the loop and after the loop.
Sub TestSimonsCreateSubList()
Dim itemlist As Variant
itemlist = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11")
SimonsCreateSubList itemlist, 3
SimonsCreateSubList itemlist, 4
SimonsCreateSubList itemlist, 5
End Sub
Sub SimonsCreateSubList(itemlist As Variant, lSliceLen As Long)
Dim inum As Variant
'* Tools->References-> Microsoft Scripting Runtime (c:\windows\system32\scrrun.dll)
Dim dicSlice As Scripting.Dictionary
Set dicSlice = New Scripting.Dictionary
For Each inum In itemlist
dicSlice.Add dicSlice.Count, inum
If dicSlice.Count = lSliceLen Then
PrintSlice dicSlice
Set dicSlice = New Scripting.Dictionary
End If
Next inum
PrintSlice dicSlice '* don't forget to print the tail end.
End Sub
Sub PrintSlice(dicSlice As Scripting.Dictionary)
Debug.Print VBA.Join(dicSlice.Items, vbNewLine)
Debug.Print "---------------------"
End Sub
I do not have access to Microsoft Office or VBA at the moment but used to be quite proficient with it and wrote this just using reference on syntax from memory. I have not tested it but am pretty sure it will work, feel free to make modifications if there are syntax errors but should be pretty close.
Edit - Applied edits suggested below, I assume it works now.
' Pass chunkLength, must be smaller than length of list
Sub SubLists(chunkLength As Long)
Dim myList As Variant
myList = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
' Length of myList divide this by chunkLength to see
' how many rows output 2-dimensional array will have
Dim listLength As Long
listLength = UBound(myList)
' arrayRows is the number of rows needed in output array
Dim arrayRows as Long
arrayRows = -Int(-listLength / chunkLength)
' If we use your example of chunks of 3, this is an array (4, 3)
' This array has 3 subarrays with 3 elements and 1 with 2 elements
Dim subLists() As Variant
' chunkLength needs to be >1 or next line is a problem
ReDim subLists(0 To arrayRows - 1, 0 To chunkLength - 1)
' row index into 2-dimensional array
Dim row As Long
row = 0
' column index into 2-dimensional array
Dim itemIndex As Long
itemIndex = 0
' just a counter
Dim listIndex As Long
For listIndex = 0 to (listLength - 1)
subLists(row, itemIndex) = myList(listIndex)
If (itemIndex < chunkLength - 1) Then
itemIndex = itemIndex + 1
Else
itemIndex = 0
row = row + 1
End If
Next listIndex
End Sub
Notes above assume that chunks are of size 3, as in the example that you linked to, but I think this code has the desired behavior. You can pass in any chunk length that is shorter than the length of the list (but more than one - see comment in code). You could also pass in an empty array to the Sub (as a 2nd parameter, though you'd need to define your starting list and array dimensions in the calling function), so that it can be used in the calling function to access the array externally, but you would need to pass it ByRef to be able to modify it in the Sub.
VB.NET: How to create a program to insert 10 elements in an array?
How to create another array from it but no repeated number should be inserted?
Here's an example of the concept:
Dim ary(9) As String
ary(0) = 1
ary(1) = 3
ary(2) = 5
ary(3) = 4
ary(4) = 6
ary(5) = 4
ary(6) = 3
ary(7) = 8
ary(8) = 9
ary(9) = 3
Dim newary() As String = ary.Distinct.ToArray
...but if you are not explicitly bound to using an array, a list would be much better. With an array, you'd have to limit yourself to the number of items you've instantiated the array with, or redim/resize it every time you add an element to it. A list wouldn't be limited like that and you could add new values on the fly.
Also, if all you need is distinct elements in the array, why not just check if your original array already contains a value before adding it, that way you skip having to copy the distinct values out of there..?
Or use this:
Dim lst As New List(Of String)
lst.AddRange({"1", "2", "3", "4", "5", "6", "7", "8", "9"})
Dim array As String() = lst.ToArray
It does the same as the other answer but its smaller
It doesnt get much shorter than this. You'll need to import Linq. array2 will contain 8 values since 1 and 9 are repeated.
Dim array1 As Integer() = {1, 1, 2, 3, 4, 5, 6, 7, 9, 9}
Dim array2 As Integer() = array.Distinct().ToArray()
A friend asked me to make a character string randomizer for a game she plays. I got the code working but now she wants to have the characters seperated every third character with a dash (or a space), but I can't get it to work. Any help will be appreciated.
For x As Integer = 1 To 10
strb.Append(chars(Int(Rnd() * UpperBound)))
If x Mod 2 = 0 Then
strb.Append("-")
The characters need to be separated, but how do I prevent the added dash at the end of the randomized characters?
Thanks guys (and girls) for your help it's working
Just append a dash (or whatever) every third character:
For x As Integer = 1 To 5
strb.Append(chars(Int(Rnd() * UpperBound)))
If x Mod 3 = 0 Then
strb.Append("-")
End If
Next
Since i haven't used those old VB function yet, i'll show you how to do it with VB.NET which could also be converted to C# easily:
Private Function RandomString(rnd As Random, size As Integer) As String
Dim chars() As String = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
Dim builder As New System.Text.StringBuilder()
For i As Integer = 0 To size - 1
builder.Append(chars(rnd.Next(0, chars.Length)))
Next
Return builder.ToString()
End Function
Let us generate a random string with 5 chars:
Dim rnd = New Random()
Dim rndString = RandomString(rnd, 5)
Note that i'm passing the random instance since. If i would create it in the method and call it in a loop, it would generate the same strings since the Random would use the same time as seed.
Edit: I've only just seen that you need to separate the result. You could use an overloaded version:
Private Overloads Function RandomString(rnd As Random, size As Integer, separator As String, everyNChar As Int32) As String
Dim builder = New System.Text.StringBuilder()
Dim chars() As String = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
For i As Integer = 0 To size - 1
If i > 0 AndAlso i Mod everyNChar = 0 Then
builder.Append(chars(rnd.Next(0, chars.Length))).Append(separator)
Else
builder.Append(chars(rnd.Next(0, chars.Length)))
End If
Next
Return builder.ToString()
End Function
Note that this will not count the separators.
You can use Regular Expressions to replace strings. It will be simple to change the regex and manage change requests :)
just replace TextBox1.Text = rndstring by :
TextBox1.Text = Regex.Replace(rndstring, "[a-zA-Z0-9]{3}", "$& ")
Note that you need to add Imports System.Text.RegularExpressions if not already done.
EDIT : I have given the above solution to insert a " " (whitespace) after every third character. If you want a hyphen (-) just change the second regex to "$&-"
If I'm understanding you correctly, change the if statement from If x Mod 2 = 0 Then to If x Mod 2 = 0 And x <> 10 Then. That way it wont append the dash if it is on the last element.
hello
Im using VB 2008
is it possible to set array items with one line code?
for example, can i do something like:
Dim array = Array("a", "b", "c", "d")
instead of:
Dim array()
array(0) = "a"
array(1) = "b"
array(2) = "c"
array(3) = "d"
thanks
You can use the following to initialize an array with explicit members.
Dim array As String() = New String(){"a", "b", "c", "d"}
This can be done with any type.
Yes using the below format:
Dim boolArr As Boolean() = New Boolean() {True, True, False, True}
I have this 2D array:
Private _Chars As String(,) = {{"`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "="},
{"¬", "!", """", "£", "$", "%", "^", "&", "*", "(", ")", "_", "+"}}
I want to Pass a Dimension (ie. the First Line) into a Function, or the Second Line into a function to switch between these two lists so that the function only requires a String() parameter not a String(,) parameter so I could loop through both like so:
Sub Example(Row as String())
For Index as Integer = 0 To Row.Count - 1
MessageBox.Show(Row(Index))
Next
End Sub
And this function would loop though 12345 etc and !"£$% etc.
If there is way to have the arrays work this was and that works in Silverlight - I would ge very grateful!
You can't do it (easily). Your best option is to create a jagged array (an array of arrays) like this:
Private _Chars String()() = { New String() {"`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "="},
New String() {"¬", "!", """", "£", "$", "%", "^", "&", "*", "(", ")", "_", "+"}}
You could then call your function like this:
Example(_Chars(0))
Example(_Chars(1))
You could use a jagged array instead.