I am using myArrayList.Contains(myString) and myArrayList.IndexOf(myString) to check if arrayList contains provided string and get its index respectively.
But, How could I check if contains a substring?
Dim myArrayList as New ArrayList()
myArrayList.add("sub1;sub2")
myArrayList.add("sub3;sub4")
so, something like, myArrayList.Contains("sub3") should return True
Well you could use the ArrayList to search for substrings with
Dim result = myArrayList.ToArray().Any(Function(x) x.ToString().Contains("sub3"))
Of course the advice to use a strongly typed List(Of String) is absolutely correct.
As far as your question goes, without discussing why do you need ArrayList, because array list is there only for backwards compatibility - to select indexes of items that contain specific string, the best performance you will get here
Dim indexes As New List(Of Integer)(100)
For i As Integer = 0 to myArrayList.Count - 1
If DirectCast(myArrayList(i), String).Contains("sub3") Then
indexes.Add(i)
End If
Next
Again, this is if you need to get your indexes. In your case, ArrayList.Contains - you testing whole object [string in your case]. While you need to get the string and test it's part using String.Contains
If you want to test in non case-sensitive manner, you can use String.IndexOf
Related
Is there a simple solution to select random strings in vb.net? I have a list of about twenty paragraphs where three need to go after each other and I want it to be random. Do I have to create a variable? Or is there a command that can be run on a button click?
One (fairly easy way) to accomplish this would be to have a collection of the paragraphs you want to use, and then use PeanutButter.RandomValueGen from the Nuget package PeanutButter.RandomGenerators (it's open-source too)
RandomValueGen.GetRandomFrom takes a collection of anything and returns a random item from the collection. As a bonus, you can specify a params list of values not to pick, so you can ensure that your paragraphs aren't repeated.
Whilst the library is written in C#, it can obviously be used from any .NET project. There are a lot of other generator methods on RandomValueGen too, if you're interested.
Full disclosure: I'm the author.
If you have a normal list, this should work:
If not, write what kind of list you have.
Dim rn As New Random
Dim selct As String = lst(rn.Next(0, lst.Count - 1))
selct is the output.
Replace lst with your list name.
if you don't want to have a dependency or need to stay on 4.0 for some odd reason or reason X, you can always try this instead
Private rnd As New Random
Public Function GetRandom(input As IEnumerable(Of String), itemToGet As Integer) As List(Of String)
If input.Count < itemToGet Then
Throw New Exception("List is too small")
End If
Dim copy = input.ToList
Dim result As New List(Of String)
Dim item As Integer
While itemToGet > 0
item = rnd.Next(0, copy.Count)
result.Add(copy(item))
copy.RemoveAt(item)
itemToGet -= 1
End While
Return result
End Function
I have to parse a string to obtain a specific value in it.
Here's an example of a string I need to parse: "#MSG 12,9: NINJUTSU"
Here I need to obtain the 12 value. The order of the value will not change, meaning that I will always aim the first number in the string; however the length of the string (12, 9, 58) is variable (but never negative) and the message (NINJUTSU) is also changing.
So far I proceed like this:
Dim tempErrorList As List(Of String) = errorMsg.Split(New Char() {":"}).ToList()
Dim listErr As List(Of String) = tempErrorList(0).Split(New Char() {","}).ToList()
Dim errCode As List(Of String) = listErr(0).Split(New Char() {" "}).ToList()
However I don't like it because of the 3 splits needed to obtain the values. I do not know how I could do it in one shot or fewer operations?
Similar to the deleted answer, you could use String.Split like so: errorMsg.Split(" ,:".ToCharArray()), which does what you're doing above but with one function call.
errorMsg.Split(" ,:".ToCharArray())(1) would give you the "12" you need.
Alternatively, you can use combinations of String.SubString() with String.IndexOf(), but the logic can become unwieldy and opaque. String.Split Alternatives (MSDN) gives more details on this approach.
In VB.NET, I have a HashTable that I would like to iterate through and conditionally remove entries from. I've written the following code that does the job perfectly, but I'd like to know if there are any creative ways to simplify the code. It just doesn't seem right to have to create a second list to perform this operation.
Here's what I've written:
Dim ModsToRemove As New List(Of String)
For Each ModKey As DictionaryEntry In ModHashTable
If ModKey.Key.ToString.Contains("Criteria") Then
ModsToRemove.Add(ModKey.Key.ToString)
End If
Next
For Each ModKey As String In ModsToRemove
ModHashTable.Remove(ModKey)
Next
Is there another way to perform the same operation that doesn't require the creation of a second list and a second loop? Is it possible to remove entries from something you are iterating through without throwing an error in VB.NET? Is doing so universally a bad idea?
With a little bit of help from Resharper and LINQ, you can simplify your expression in the following ways.
This code block here can be rewritten to use LINQ instead of the embedded IF statement
For Each ModKey As DictionaryEntry In ModHashTable
If ModKey.Key.ToString.Contains("Criteria") Then
ModsToRemove.Add(ModKey.Key.ToString)
End If
Next
Is equivalent to
Dim modsToRemove As List(Of String) = (From modKey As DictionaryEntry In
modHashTable Where modKey.Key.ToString.Contains("Criteria")
Select modKey.Key.ToString).ToList()
Combining this with your actual loop to remove the items from the Hashtable, you should be able to get the equivalent functionality of your example above with the following 3 lines of code:
For Each key As String In (From modkey As DictionaryEntry In modHashTable Where modkey.Key.ToString.Contains("Criteria") Select modkey.Key.ToString).ToList()
modHashTable.Remove(key)
Next
Basicly I have a program that retrieves data and parses it, which is fine, so it starts from:
11:981.8 which equals to November 981.8 now what I have done is split the "November" and the "981.8" into 2 different arrays, with other similar data, now what I need to be able to do, is sort the array in either Ascending or Descending order, however keeping in tact, the November and 981.8 side by side in a list box.
My current code is:
Private Sub sortData(ByVal strYear As String, ByVal strSort As String)
lbDispData.Items.Clear()
Dim strData As String = My.Settings.usage2011
Dim arrRawData() As String
Dim arrMonth As New ArrayList
Dim arrKilo As New ArrayList
arrRawData = strData.Split("_")
For Each strUsage As String In arrRawData
Dim arrSmall As String()
arrSmall = strUsage.Split(":")
arrSmall(0) = MonthName(arrSmall(0))
arrMonth.Add(arrSmall(0))
arrKilo.Add(arrSmall(1))
Next
If strSort = 0 Then
'Sort in ascending order
ElseIf strSort = 1 Then
'Sort in descending order
End If
End Sub
Or If possible is there a better way?
EDIT: Just to mention, there are many more values, not just November and 981.8, there would be for example December and 128.1, January and 191.1, etc.
Don't use two arrays. Use one array or List, and each item in the array should be either an instance of a custom Class which would have Month and Kilo properties, or a Tuple instance.
Then you can sort by whichever property you want, and don't have to worry about related information staying together.
To create a Tuple for an item, you use Tuple.Create:
Dim myTuple = Tuple.Create(monthValue, kiloValue)
Then you can access values from the Tuple using Item1, Item2, etc.
Dim month = myTuple.Item1
Dim kilo = myTuple.Item2
There are essentially two ways to store this kind of data: array of structures, or structure of arrays. Your implementation, at present, is the latter. As you suspect, the former is typically preferred in languages which provide access to objects and user-defined types.
To solve this problem using an array-of-structures data representation, you will define your own type - for instance, you could call it MonthFloatPair or something more relevant to your application, or you could simply use a built-in type that suits your needs - and have a single array of type MonthFloatPair. To add a MonthFloatPair, you'd parse a string exactly as you are now, and then simply assign the month to one member of MonthFloatPair and the number (Kilo?) to another. Then all you would have to do is to write a method to provide an ordering comparison of MonthFloatPair objects (I believe this is possible in vb.net, at any rate), and then sort this array normally however you'd like.
To solve this problem using a structure-of-arrays data representation, you do exactly what you're doing now. To sort, sort normally as you would for the array you're sorting on, with one caveat: every time you change the position of an element of the array on which you're basing the sorting (e.g., by exchanging in O(n^2) sorts, or placing into a new array as in MergeSort), you need to move the corresponding (same index) element in the other array in the same manner.
People often tell me not to use ArrayList for making my arrays in VB.NET.
I would like to hear opinions about that, why shouldn't I? What is the best method for creating and manipulating array contents, dimensions etc?
Thanks.
Use generic lists instead. ArrayList is not typed, meaning that you can have a list with strings, numbers, +++. Rather you should use a generic list like this:
Dim list1 As New List(Of String) ' This beeing a list of string
The lists-class also allows you to expand the list on the fly, however, it also enforces typing which helps write cleaner code (you don't have to typecast) and code that is less prone to bugs.
ArrayList is gennerally speaking just a List(Of Object).
ArrayLists are not type checked so you will need to do a lot of boxing/unboxing. Use a .net collection instead that support generics like List.
Because List does not have to unbox your objects it boasts a surprisingly better performance than Arraylist.
ArrayLists are less performant and memory-extensive:
Dim list1 As New ArrayList
For i As Integer = 1 To 100000000
list1.Add(i)
Next
' --> OutOfMemoryException after 13.163 seconds, having added 67.108.864 items
Dim list2 As New List(Of Integer)
For i As Integer = 1 To 100000000
list2.Add(i)
Next
' --> finished after 1.778 seconds, having added all values
Because its not strongly typed. Use a List(Of T) which T is your type.