VB.net Error when storing lists in array - vb.net

I have the following code, the objective of it is to take an initial list and to take each element within the list and store it in an array of lists, with each list in the array, holding each element in its own list. For instance
The list 2, 2, 3, 3, 3, 3, 5, 5, 7, 9, 9. Would create five lists:
List 1: 2, 2
List 2: 3, 3, 3, 3,
List 3: 5, 5
list 4: 7
List 5: 9, 9
This is my current code:-
Dim cnt As Integer = 0
Dim lists(uniqueFactors.Count) As List(Of Integer)
Dim saver As Integer = factors.Item(0)
Console.WriteLine(saver)
For Each i In factors
lists(cnt).Add(i)
If saver <> i Then
cnt = cnt + 1
End If
saver = i
Next
Thanks all in advance!

You'd probably be better off using a Dictonary<TKey, TValue>.
Dim storage As New Dictionary(Of Integer, Integer)
' Number Occurrences
' | |
storage.Add(2, 2)
storage.Add(3, 4)
storage.Add(5, 2)
storage.Add(7, 1)
storage.Add(9, 2)
You can iterate the list like this:
For Each item As KeyValuePair(Of Integer, Integer) In storage
Dim number As Integer = item.Key
Dim occurrences As Integer = item.Value
Next
Get the number of occurrences for a given number like this:
Dim number As Integer = 9
Dim occurrences As Integer = storage(number) 'Return: 2
Change the number of occurrences:
storage.Item(number) = 4 'Set to 4
storage.Item(number) += 1 'Increase from 2 to 3
storage.Item(number) -= 1 'Decrease from 2 to 1
Create an enumerator, array and/or list of occurrences for a given number:
Dim iterator As IEnumerable(Of Integer) = Enumerable.Repeat(number, occurrences).ToList()
Dim array As Integer() = Enumerable.Repeat(number, occurrences).ToArray()
Dim list As List(Of Integer) = Enumerable.Repeat(number, occurrences).ToList()
You can also write an extension method:
Public Module Extensions
<System.Runtime.CompilerServices.Extension()>
Public Function ToList(Of TKey)(source As Dictionary(Of TKey, Integer), key As TKey) As List(Of TKey)
Return Enumerable.Repeat(key, source.Item(key)).ToList()
End Function
End Module
Now you create a list by simply writing:
Dim occurrences As List(Of Integer) = storage.ToList(number)

Why not use a List of Lists like this?
Dim last As Integer
Dim first As Boolean = True
Dim ints As List(Of Integer)
Dim lists As New List(Of List(Of Integer))
For Each i In factors
If first Then
first = False
ints = New List(Of Integer)
ints.Add(i)
lists.Add(ints)
last = i
ElseIf i = last Then
ints.Add(i)
Else
ints = New List(Of Integer)
ints.Add(i)
lists.Add(ints)
last = i
End If
Next

Related

VB.NET combination Array x2

I would like all possible combinations from two string arrays.
Both arrays must have same length.
Result must keep order
For example :
dim lStr1() as string = {"One", "Two", "Three"}
dim lStr2() as string = {"EditOne", "EditTwo", "EditThree"}
dim res() as string = myAwesomeFunction(lStr1, lStr2)
// res :
One Two Three
One Two EditThree
One EditTwo Three
One EditTwo EditThree
EditOne Two Three
EditOne Two EditThree
EditOne EditTwo Three
EditOne EditTwo EditThree
It's like the binary composition of 2 arrays of strings.
Here's another solution. Since only 2 arrays are involved, we can bit-fiddle to get all of the "combinations". The & " " is just to format the output to match the example.
Private Function myAwesomeFunction(Array1() As String, Array2() As String) As String()
If Array1.Length <> Array2.Length Then
Throw New ArgumentException("Array lengths must be equal.")
End If
Dim combos(CInt(2 ^ Array1.Length) - 1) As String
For i As Integer = 0 To combos.Count - 1
For j = 0 To Array1.Length - 1
If (i And (1 << j)) > 0 Then
combos(i) += Array2(j) & " "
Else
combos(i) += Array1(j) & " "
End If
Next
Next
Return combos
End Function
The following code will produce the array in your example. It should work for any pair of input arrays. The function checks that the input arrays are of the same length.
The GetPermutations function is taken from a more general class I use for generating permutations of numbers. It returns arrays of total Integers between 0 and choose - 1, and being an Iterator function, it returns the next array each time it is called.
In order to match your example, I returned an array of String where each element is a single string consisting of each of the selected strings separated by spaces. You may find it more useful to return a List(Of String()) or even a List(Of List(Of String))
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lStr1() As String = {"One", "Two", "Three"}
Dim lStr2() As String = {"EditOne", "EditTwo", "EditThree"}
Dim res() As String = myAwesomeFunction(lStr1, lStr2)
End Sub
Function MyAwesomeFunction(lStr1() As String, lStr2() As String) As String()
Dim combos As New List(Of String)
If lStr1.Length <> lStr2.Length Then Throw New ArgumentException("Arrays must have the same length")
For Each combo() As Integer In GetPermutations(lStr1.Length, 2)
Dim elem As New List(Of String)
For i As Integer = 0 To combo.Length - 1
elem.Add(If(combo(i) = 0, lStr1(i), lStr2(i)))
Next
combos.Add(String.Join(" ", elem))
Next
Return combos.ToArray
End Function
Public Iterator Function GetPermutations(choose As Integer, total As Integer) As IEnumerable(Of Integer())
Dim totals() As Integer = Enumerable.Repeat(Of Integer)(total, choose).ToArray
Dim value(choose - 1) As Integer
Do
Yield value
For index As Integer = choose - 1 To 0 Step -1
value(index) += 1
If value(index) < totals(index) Then Continue Do
value(index) = 0
Next
Exit Do
Loop
End Function

Using VB.NET 2010, How do I rotate the elements in an array?

For instance my array is {4,6,9,3,1}
And I want to cycle it X amount of times, for example 3 times,
I want my array to become {3,1,4,6,9}
Is there an easy way to do this in VB.NET?
Thank you
Function CycleArray(ByVal Arr() As Integer)
Dim Tmp As Integer = Arr(0)
Dim Arr2 = Arr.Skip(1).ToArray()
Arr2(UBound(Arr2) + 1) = Tmp
Return Arr2
End Function
You will find that using List is far easier than using Arrays in most cases. To try this call the function like this:
Dim MyArray() As Integer = {4, 6, 9, 3, 1}
MyArray = LeftRotateArray(MyArray, 3)
the function looks like this:
Private Function LeftRotateArray(theArray() As Integer, Shift As Integer) As Integer()
Dim shiftVal As Integer = Shift Mod theArray.Length 'in case Shift is larger than array
Dim rv As List(Of Integer) = theArray.ToList
For ct As Integer = 1 To shiftVal
rv.Add(rv(0))
rv.RemoveAt(0)
Next
Return rv.ToArray
End Function
The method is straight forward. Copy the array to a list and then move elements from the front to the rear until you have completed the desired iterations. The return creates an array from the list.
or using this method from Jon Bentley's 'Programming Pearls':
Private Function LeftRotateArray(theArray() As Integer, Shift As Integer) As Integer()
Dim shiftVal As Integer = Shift Mod theArray.Length 'in case Shift is larger than array
Dim rv(theArray.GetUpperBound(0)) As Integer
Array.Copy(theArray, rv, theArray.Length)
Array.Reverse(rv, 0, shiftVal)
Array.Reverse(rv, shiftVal, rv.Length - shiftVal)
Array.Reverse(rv, 0, rv.Length)
Return rv
End Function
Since it's essentially cutting and pasting a part of the original array at a specific place it can be done in one action. As dbasnett said it's easier to work with a List or IEnumerable, if you're focusing on clarity of code. Performance wise other solutions might be better.
Dim numbers = New Integer() {4, 6, 9, 3, 1}
Dim result = RotateRight(numbers, 3)
 
Public Function RotateRight(numbers As Integer(), offset As Integer) As Integer()
Dim list = numbers.ToList()
Return list.Skip(offset).Concat(list.Take(offset)).ToArray()
End Function
I think you can simply do Array.Copy. You would need to do it in two parts...
Function CycleArray(Arr() As Integer, cycleTimes As Integer) As Integer()
Dim Arr2() As Integer
ReDim Arr2(Arr.Length - 1)
cycleTimes = cycleTimes Mod Arr.Length
Array.Copy(Arr, cycleTimes, Arr2, 0, Arr.Length - cycleTimes)
Array.Copy(Arr, 0, Arr2, Arr.Length - cycleTimes, cycleTimes)
Return Arr2
End Function

Sorting using an index number

How do i implement a index based sort in vb.net
Could someone guide me. By giving me a head start
eg
array = 9 8 7 6 5 4 3 2 1
Index Number = 5
Counting from 9 and the 5th character is 5.
So the first sorted character is 5.
Remove 5 and remains 9 8 7 6 4 3 2 1
start value should be from 4(current 5th character) now 5th character is 9 since it's circular
unsorted array : 8 7 6 4 3 2 1
sorted array : 5 9
any hints
First off, I definitely wouldn't call this "sorting"; it's a bit more like deterministically (non-randomly) "shuffling" the array. But I'll take a stab at this…
Basically, start by using List(Of T) rather than arrays, because they allow you to easily and remove at any point in the list, rather than arrays which are a fixed size. Next, use a running counter to track your current position in the input list, and use the Mod operator to make the index effectively 'wrap' around the end of the list. Use a While loop to continue until all the items from the input have been processed. It should look something like this:
Dim input As New List(Of Integer) From { 9, 8, 7, 6, 5, 4, 3, 2, 1 }
Dim stepBy As Integer = 5
Dim index As Integer = 0
Dim output As New List(Of Integer)
While input.Count > 0
index = (index + stepBy - 1) Mod input.Count
output.Add(input(index))
input.RemoveAt(index)
End While
In this case the output is:
5, 9, 3, 6, 7, 4, 1, 8, 2
I thought this was an interesting question and I loved the answer by p.s.w.g....
...but I was curious to see if any of the built-in .Net collections would facilitate a fairly trivial circular list.
This is what I came up with using the LinkedList class:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim originalIntegers() As Integer = {9, 8, 7, 6, 5, 4, 3, 2, 1}
Dim output As New List(Of Integer)
Dim circleInts As New CircularIntegerList(originalIntegers)
circleInts.MoveForward(4) ' move forward 4 from the 1st to get the 5th slot
While circleInts.Count > 0
If circleInts.Current.HasValue Then
output.Add(circleInts.Current)
End If
circleInts.RemoveCurrent() ' next number in sequence becomes the current one
circleInts.MoveForward(4) ' move forward another 4, net jump is 5 from the deleted one
End While
Dim result As String = String.Join(",", output.Select(Function(x) x.ToString).ToArray)
Debug.Print(result)
End Sub
End Class
Public Class CircularIntegerList
Private values As New LinkedList(Of Integer)
Private _current As LinkedListNode(Of Integer)
Public Sub New(ByVal data() As Integer)
If data.Length > 0 Then
values = New LinkedList(Of Integer)(data)
_current = values.First
End If
End Sub
Public ReadOnly Property Current As Integer?
Get
If Not IsNothing(_current) Then
Return _current.Value
Else
Return Nothing
End If
End Get
End Property
Public ReadOnly Property Count As Integer
Get
Return values.Count
End Get
End Property
Public Sub RemoveCurrent()
If Not IsNothing(_current) Then
Dim tmp As LinkedListNode(Of Integer) = If(IsNothing(_current.Next), values.First, _current.Next)
values.Remove(_current)
If values.Count > 0 Then
_current = tmp
Else
_current = Nothing
End If
End If
End Sub
Public Sub MoveForward(Optional ByVal NumberOfJumps As Integer = 1)
If Not IsNothing(_current) Then
For i As Integer = 1 To NumberOfJumps
_current = If(IsNothing(_current.Next), values.First, _current.Next)
Next
End If
End Sub
End Class

For loop make new variables for you - VB.Net

I'm trying to make a for loop for will make a new variable for me, every step. I want something like this. What ever step I am on, say, x = 2, it Dims newVar2, if x = 3: Dim newVar3
Is there any way to do that? I was hoping something like, Dim newVar & x would work, but of course now.
I was trying to do it as an array, but I'm not sure how to do that, or ReDimming, so examples would be great!
To create a collection of variable values inside a for loop, you should use a List(Of t) object or something similar (For Example Dictionary).
To do this with a List(Of t) you can do the following :
Dim varList As New List(Of Integer)
For i As Integer = 0 To 10
varList.add(i)
Next
Or if you want to do it with the variable names you mentioned, try :
Dim varList As New List(Of String)
For i As Integer = 0 To 10
varList.add("newVar" & i)
Next
To retrieve the value from a List use the following : Dim result As String = varList(0)
Alternatively you can use a Dictionary object to store Key/Value pairs :
Dim varList As New Dictionary(Of String, Integer)
For i As Integer = 0 To 10
Dim k As Integer = 0
varList.add("newVar" & i, k)
Next
Becareful though as a Dictionary object can only contain unique Keys. To return the value find it as : Dim result As Integer = varList("newVar0")
basic array:
Dim Arr(1000) As Integer
For i As Integer = 0 To 999
Arr(i) = YYYYY
Next
trick for dynamic size:
Dim max As Integer = XXXXXX
Dim Arr(1000) As Integer
For i As Integer = 0 To max
'if too small, Increasing array without loss old data
If Arr.Length = i Then
ReDim Preserve Arr(Arr.Length + 1000)
End If
Arr(i) = YYYYY
Next
or, use list:
Dim max As Integer = XXXXXX
Dim list As New List(Of Integer)
For i As Integer = 0 To max
list.Add(YYYYY)
Next
The other answers are technically correct, but you probably don't need the iteration loops. You can probably do this in a single line of code:
Dim varList As Dictionary(Of String, String) = Enumerable.Range(0, 10).ToDictionary(Function(k) "newVar" & k, Function(v) "Some value for newVar" & v)
Dim myInts As New List(Of Int)
For i = 0 To 10
myInts.Add(i)
Next

VB.NET: Check if List items are equal and have same count

How can I detect whether the items of two given lists are equal?
Dim list1 As New List(Of Integer)
list1.AddRange({1, 2, 3})
Dim list2 As New List(Of Integer)
list2.AddRange({3, 2, 1})
If I compare them using SequenceEqual I get False because the order of the items is not the same. How can I compare them without sorting them first, though?
EDIT: Please take into account that this should respect duplicates, for example {1, 2, 3, 1} is not the same as {1, 2, 3} (item 1 occurs two times in the first list).
If you want to know if both lists contain the same items you can use Enumerable.Except:
Dim bothContainSameItems As Boolean
If list1.Count > list2.Count Then
bothContainSameItems = Not list1.Except(list2).Any()
Else
bothContainSameItems = Not list2.Except(list1).Any()
End If
or, with the help of HashSet(Of T):
Dim l1Set = New HashSet(Of Integer)(list1)
Dim l2Set = New HashSet(Of Integer)(list2)
bothContainSameItems = l1Set.SetEquals(l2Set)
Note that both approaches will ignore duplicates. So they will return equal for:
list1.AddRange({1, 1, 2, 3})
list2.AddRange({3, 2, 1, 3})
Here's a possible way to also check if all numbers have the same count in both lists:
bothContainSameItems = list1.Count = list2.Count
If bothContainSameItems Then
Dim l1Ordered = list1.OrderBy(Function(i) i).ToList()
Dim l2Ordered = list2.OrderBy(Function(i) i).ToList()
For i As Int32 = 0 To l1Ordered.Count - 1
If l1Ordered(i) <> l2Ordered(i) Then
bothContainSameItems = False
Exit For
End If
Next
End If
Also working with
Dim list1 As New List(Of Integer)
list1.AddRange({1, 2, 3})
Dim list2 As New List(Of Integer)
list2.AddRange({3, 2, 1})
Dim list3 = list1.Union(list2)
if list3.OrderBy(Function(i) i).SequenceEqual(list1.OrderBy(Function(i) i)) then
Console.WriteLine("Equal")
else
Console.WriteLine("Not Equal")
end if
IEnumerable.Union
Return Value: An IEnumerable(Of T) that contains the elements from both input sequences,
excluding duplicates.
<System.Runtime.CompilerServices.Extension()> _
Function AreItemsEqual(Of T)(col1 As IEnumerable(Of T), col2 As IEnumerable(Of T)) As Boolean
' performance checks
If col1 Is col2 Then Return True
If col1 Is Nothing OrElse col2 Is Nothing Then Return False
If col1.Count <> col2.Count Then Return False
' compare their elements
Dim o1 As IEnumerable(Of T) = col1.OrderBy(Function(i) i)
Dim o2 As IEnumerable(Of T) = col2.OrderBy(Function(i) i)
Return o1.SequenceEqual(o2)
End Function
Usage:
If list1.AreItemsEqual(list2) Then
...