Array of Integers Comparing Integers VB.NET - vb.net

Basically I have and array of integers that vary in size. I need to compare each number to each other number and display which number is repeated. For example:
Dim ints() As Integer = {1,2,2,5,4,6}
The number that shows up more than once is 2.
How can I run through the array and compare each integer with the numbers in the array. I tried a for loop but it didn't return the value I was looking for. I am new to VB.NET and do not understand fully.

Dim ints() As Integer = {1,2,2,5,4,6}
Dim repeatedNumbers = ints.GroupBy(Function(intValue) intValue) _
.Where(Function(grp) grp.Count > 1)
For each grp in repeatedNumbers
Console.WriteLine("Number {0} is repeated {1} times", grp(0), grp.Count)
Next
What this code does:
We first call GroupBy, which groups items by their value. The Function gets the grouping key, in this case we simply group by the array's value itself. This call returns a sequence of
groups. There is one group for every unique value in the array. The
group contains all items that correspond to a unique value. So if a value appears twice in the array, there will be a group which contains two ints with this value.
We call Where to filter groups. We only want groups for which the count is greater than one, so that only duplicate values are considered.
We then loop through the result. grp(0) gives us the first number in the group (we could have picked any number in the group, since all numbers in a group are the same!) and the Count property gives us the number of repetitions.

I would try it with something like this:
Dim ints() As Integer = {1, 2, 2, 5, 4, 6}
Array.Sort(ints)
For i = 1 To ints.GetUpperBound(0)
If ints(i) = ints(i - 1) Then MessageBox.Show(String.Format("{0} is repeated", ints(i)))
Next
Doing it like this on a sorted array keeps down the nesting.
I've not tested this but it should be along the right lines.

You could use LINQ to find the duplicates:
Dim repeating = (From n In ints
Group By n Into Dups = Group
Where Dups.Count > 1
Select Dups.First).ToArray()
This returns an Array of integers which only contains numbers that are not unique in the original array.
So this displays the repeating number(s):
MessageBox.Show(String.Format("Duplicates found: {0}", String.Join(","c, repeating)))

Related

Refined list sorting by substring integer after alphabetical sorting

I have some information in a list (called listLines). Each line below is in a List(Of String).
1|This is just a header
3|This is just a footer
2|3456789|0000000|12312312313|BLUE|1|35.00
2|7891230|0000000|45645645655|BLUE|1|22.00
2|7891230|0000000|45645645658|RED|2|13.00
2|3456789|0000000|12312312316|RED|2|45.00
2|3456789|0000000|12312312317|YELLOW|5|-9.00
2|3456789|0000000|12312312315|ORANGE|3|15.00
2|7891230|0000000|45645645659|YELLOW|5|32.00
2|3456789|0000000|12312312314|GREEN|4|-20.00
2|7891230|0000000|45645645656|GREEN|4|39.00
2|7891230|0000000|45645645657|ORANGE|3|-18.50
I'm doing a listLines.sort() on the list to sort it alphabetically. Below is what I get after the .sort().
1|This is just a header
2|3456789|0000000|12312312313|BLUE|1|35.00
2|3456789|0000000|12312312314|GREEN|4|-20.00
2|3456789|0000000|12312312315|ORANGE|3|15.00
2|3456789|0000000|12312312316|RED|2|45.00
2|3456789|0000000|12312312317|YELLOW|5|-9.00
2|7891230|0000000|45645645655|BLUE|1|22.00
2|7891230|0000000|45645645656|GREEN|4|39.00
2|7891230|0000000|45645645657|ORANGE|3|-18.50
2|7891230|0000000|45645645658|RED|2|13.00
2|7891230|0000000|45645645659|YELLOW|5|32.00
3|This is just a footer
With that said, I need to output this information to a file. I'm able to do this ok. I still have a problem though. There is a sequence number in the above data at position 5 just after the listed colors (RED, BLUE, ETC..) that you can see. It's just before the last value which is a decimal type.
I need to further sort this list, keeping it in alphabetical order since position 2 is an account number and I want to keep the account numbers grouped together. I just want them to be resorted in sequential order based on the sequence number.
I was looking at another thread trying to figure out how I can do this. I found a piece of code like listLines.OrderBy(Function(q) q.Substring(35)).ToArray. I think this would probably help me if this was a fixed length file, it isn't however. I was thinking I can do some kind of .split() to get the 5th piece of information and sort it but then it's going to unalphabetize and mix the lines back up because I don't know how to specify to still keep it alphabetical.
Right now I'm outputting my alphabetical list like below so I can format it with commas and double quotes.
For Each listLine As String In listLines
strPosition = Split(listLine, "|")
Dim i As Integer = 1
Dim iBound As Integer = UBound(strPosition)
Do While (i <= iBound)
strOutputText = strOutputText & Chr(34) & strPosition(i) & Chr(34) & ","
i += 1
Loop
My main question is how do I re-sort after .sort() to then get each account (position1) in sequential order (position 5)? OR EVEN BETTER, how can I do both at the same time?
The List(Of T) class has an overload of the Sort method that takes a Comparison(Of T) delegate. I would suggest that you use that. It allows you to write a method or lambda expression that will take two items and compare them any way you want. In this case, you could do that like this:
Dim items = New List(Of String) From {"1|This Is just a header",
"3|This Is just a footer",
"2|3456789|0000000|12312312313|BLUE|1|35.00",
"2|7891230|0000000|45645645655|BLUE|1|22.00",
"2|7891230|0000000|45645645658|RED|2|13.00",
"2|3456789|0000000|12312312316|RED|2|45.00",
"2|3456789|0000000|12312312317|YELLOW|5|-9.00",
"2|3456789|0000000|12312312315|ORANGE|3|15.00",
"2|7891230|0000000|45645645659|YELLOW|5|32.00",
"2|3456789|0000000|12312312314|GREEN|4|-20.00",
"2|7891230|0000000|45645645656|GREEN|4|39.00",
"2|7891230|0000000|45645645657|ORANGE|3|-18.50"}
items.Sort(Function(x, y)
Dim xParts = x.Split("|"c)
Dim yParts = y.Split("|"c)
'Compare by the first column first.
Dim result = xParts(0).CompareTo(yParts(0))
If result = 0 Then
'Compare by the second column next.
result = xParts(1).CompareTo(yParts(1))
End If
If result = 0 Then
'Compare by the sixth column last.
result = xParts(5).CompareTo(yParts(5))
End If
Return result
End Function)
For Each item In items
Console.WriteLine(item)
Next
If you prefer a named method then do this:
Private Function CompareItems(x As String, y As String) As Integer
Dim xParts = x.Split("|"c)
Dim yParts = y.Split("|"c)
'Compare by the first column first.
Dim result = xParts(0).CompareTo(yParts(0))
If result = 0 Then
'Compare by the second column next.
result = xParts(1).CompareTo(yParts(1))
End If
If result = 0 Then
'Compare by the sixth column last.
result = xParts(5).CompareTo(yParts(5))
End If
Return result
End Function
and this:
items.Sort(AddressOf CompareItems)
Just note that this is rather inefficient because it splits both items on each comparison. That's not a big deal for a small list but, if there were a lot of items, it would be better to split each item once and then sort based on those results.

How to pass Value from Last Loop?

I have been attempting many ways to retrieve 2 collections together, while the first collection holds a comma-separated value in a column, we can not find a solution to passing the first collection value to the second For Each.
This code simply retrieves database rows and adds each result to our list control using the Add() method.
Dim transferstable As New DataTable
count = 0
For Each row As DataRow In transferstable.Rows
Dim name = Truncate(row.Item("name"), 42)
ListControl1.Add(name, row.Item("username")", row.Item("added"), avatars, row.Item("online"), images(count), 0)
count += 1
Next
Problem
We need to nest the loops, so we get the value from the first collection from the "avatars" column (image1,image2,image3) and call it from Add() - 4th parameter.
We only get always 1 string result into the view, while the actual query reports many rows with 2 strings (image1, image2) so I tried this:
Dim lst As New List(Of String) From {
transferstable.Rows(0).Item(8)
}
count = 0
For Each item As String In lst
For Each row As DataRow In transferstable.Rows
Dim name = Truncate(row.Item("name"), 42)
ListControl1.Add(name, row.Item("username")", row.Item("added"), item, row.Item("online"), images(count), 0)
count += 1
Next
Next
And the still the same single result! (8) is the GROUP_CONCAT column for "avatars" How do we pass this list over to the 4th parameter?
We want to retrieve these as URL remote images and render them to view with Bitmap.
Expected result:
A list of 15x15 pictures that represent each split result from GROUP_CONCAT(avatars)
I've been at all different ways to do this for most of the day, I know nesting is the right direction but I can't figure out why only 1 result is coming back (image1 - not image1,image2, etc.)
Some physical image files do not exist anymore, so rendering that to view also has it halt after a few single string results, so it quits and gives an error, like a 404 but does not proceed with the 180 other rows.
https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/for-each-next-statement

How do I generate random numbers from a list of specific numbers that I have?

I want my application to populate random sets of numbers using a list of specific numbers that i chose. For example; I have a set of numbers (1,3,5,9,21,70,56). I want to be able to randomize the order in which these numbers are selected. Is that possible?
If you want to generate a list of 1000 numbers using only those you gave:
Dim r as New Random()
Dim thousand as New List(Of Integer)(1000)
'short way to create an array
Dim onlyFrom = {1,3,5,9,21,70,56}
For i = 1 to 1000
thousand.Add(onlyFrom(r.Next(0, onlyFrom.Length)))
Next i
It repeatedly asks a Random for a random integer between 0 and the array length. Next() may return the lower number, but never the upper number. Documentation
If you want to shuffle those numbers you gave into a random order, easy way to use LINQ:
Dim r as New Random()
Dim onlyFrom = {1,3,5,9,21,70,56}
Dim shuffled = onlyFrom.OrderBy(Function(x) r.Next()).ToArray()
Note: Do not use New Random() in a loop
Randomize()
Dim NumberList= {1,3,5,9,21,70,56}
' Generate random value between 1 and 7, or use NumberList length to make it generic
Dim value As Integer = CInt(Int(( 7 * Rnd()) + 1))
return NumberList(value-1)
* The above code may produce the same value multiple times in a series. so if the requirement is that a different value be produced from the array each time when the code is called seven times, this wouldn't work *
If the requirement is to have a different value from the array each time for the first 7 calls, you may use Shuffle function as laid out here Shuffling an array of strings in vb.net

Function to order numbers; find common difference and gap

I have a vb6 function that will take up to 7 numbers, order them, find a common difference. There will be a gap in this sequence of numbers. I also want to identify the missing number.
Example input is 19,17,20,and 16. The output should be an array 16,17,18,19,20 in this order. Any help? I may be able to interpret vb.net code to vb6, but vb6 is preferred to me.
Here’s an outline of what needs to be done:
Find the smallest and largest number
Create an array with enough entries to hold the full range from the smallest to largest
Fill the array with the numbers from lowest to highest.
Note that you don’t need to sort the numbers at all. You just need to find the extreme values.
Here’s a code outline in VB6:
Function RangeFrom(ParamArray Numbers() As Long) As Long()
Dim Lowest As Long
Dim Highest As Long
Lowest = Numbers(0)
Highest = Numbers(0)
Dim Number As Long
For Each Number In Numbers
If Number < Lowest Then Lowest = Number
If Number > Highest Then Highest = Number
Next
Dim Result(0 To Highest - Lowest) As Long
Dim I As Long
For I = 0 To Highest - Lowest
Result(I) = Lowest + I
Next
FromRange = Result
End Function
Since you have tagged VB.NET as well, this should be convertible to VB6(i've avoided Linq):
Public Shared Function FillGaps(input As Int32()) As Int32()
Dim output = New List(Of Int32)
Array.Sort(input)
' now we'll find the min/max-values at the first/last indices
For i As Int32 = input(0) To input(input.Length - 1)
output.Add(i)
Next
Return output.ToArray()
End Function
Use it in the following way :
Dim intArray = {19, 17, 20, 16}
intArray = FillGaps(intArray)
Note that this approach skips duplicates.

Visual basic list box

I am trying to get each item in a list box into a string array. However, I keep getting an index error and I am not sure why. I am doing this so i can perform a LINQ on the array. Here is the error and the code in question. Thank you for any help in advance.
Error:
InvalidArgument=Value of '16' is not valid for 'index'.
Parameter name: index
Code:
Dim size As Integer = lstBoxSeats.Items.Count()
Dim seats(size) As String
For i = 0 To size
seats(i) = lstBoxSeats.Items(i).ToString()
Next
Your array is zero based, the count is actual number of items. You need to subtract 1 from the count for your index.
i.e.
Correction: just realized that you were using count to dimension your seats array which is leaving a empty position in your seats array
Dim size As Integer = lstBoxSeats.Items.Count()-1 'Subtract 1 here instead of in the For statement
Dim seats(size) As String
For i = 0 To size
seats(i) = lstBoxSeats.Items(i).ToString()
Next
This is because index is zero based i.e starts from 0 while Count is the amount of items which starts from 1, so if there are 16 items it means that maximum index is 15 (0-15) and count is 16(1-16)