I have a list of numbers with anywhere from 1 to 5 digits (The numbers are values in a DataGridView column). There is only one of the numbers that is unique. All of the other numbers are duplicated at least once. I need to get the one unique number that is not duplicated.
There are many good articles on line which skirt around my task, some using linq but none look for the one only item. I found the code shown below but I don't understand what the Function(X) is.
Dim distinct = mynumber.DistinctBy(Function(X) X.muNumber).ToList
I used a Linq query on a list of numbers and called .ToList on the query so it would result in the more friendly List(Of Integer) rather than an IEnumerable. Since you seemed sure that you only had one unique value I printed the first item of the list to the immediate window. If you were to have more unique values you could just loop through unique.
I am sure this is not the most efficient way to do this but it should work.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lstNumbers As New List(Of Integer) From {1, 5, 77, 1, 32, 5, 77}
Dim unique = (From i In lstNumbers
Let ct = (From i2 In lstNumbers Where i2 = i Select i2).Count
Where ct = 1
Select i).ToList
Debug.Print(unique(0).ToString)
End Sub
EDIT
As per OP's comment - How to use a string of numbers.
'This line won't compile unless you put quotes around it.
Dim nums As String = "1,2, 3, 4, 1, 2, 3, 4, 5"
'There are a few steps to change this string into a list of numbers.
'First get an array of strings
Dim splitNums = nums.Split(","c) 'This overload of Split takes a Char array. The c tells it that this is a char not a string.
'Each of the strings in the array are trimmed of any leading or trailing spaces.
'Then the string is converted to an Integer
'Finally the whole query is changed to a list
Dim lstNumbers = (From i In splitNums
Select CInt(i.Trim)).ToList
'and now lstNumbers is indeed a list of Integers which can be used in the code.
EDIT 2
To see if there are more than one unique numbers use a For Each loop.
For Each i In unique
TextBox1.Text &= i.ToString & ", "
Next
Related
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.
In VB.net (Visual Studio 2015) how can I get the nth string (or number) in a comma-separated list?Say I have a comma-separated list of numbers like so:13,1,6,7,2,12,9,3,5,11,4,8,10How can I get, say, the 5th value in this string, in this case 12?I've looked at the Split function, but it converts a string into an array. I guess I could do that and then get the 5th element of that array, but that seems like a lot to go through just to get the 5th element. Is there a more direct way to do this, or am I pretty much limited to the Split function?
In case you are looking for an alternative method, which is more basic, you can try this:
Module Module1
Sub Main()
Dim a As String = "13,1,6,7,2,12,9,3,5,11,4,8,10"
Dim counter As Integer = 5 'the number you want (in this case, 5th one)
Dim movingcounter As Integer = 0 'how many times we have moved
Dim startofnumber, endofnumber, i As Integer
Dim numberthatIwant As String
Do Until movingcounter = counter
startofnumber = InStr(i + 1, a, ",")
i = startofnumber
movingcounter = movingcounter + 1
Loop
endofnumber = InStr(startofnumber + 1, a, ",")
numberthatIwant = (Mid(a, startofnumber + 1, endofnumber - startofnumber - 1))
Console.WriteLine("The number that I want: " + numberthatIwant)
Console.ReadLine()
End Sub
End Module
Edit: You can make this into a procedure or function if you wish to use it in a larger program, but this code run in console mode will give the output of 12.
The solution provided by Plutonix as a comment to my question is straightforward and exactly what I was looking for, to wit:result = csv.Split(","c)(5)In my case I was incrementing a variable each time my program ran and needed to get the nth character or string after the incremented value. That is, if my program had incremented the variable 5 times, then I needed the string after the 4th comma, which of course, is the 5th string. So my solution was something like this:result = WholeString.Split(","c)(IncrementedVariable)Note that this is a zero-based variable.Thanks, Plutonix.
I am trying to make a simple keygen app (hoping to evolve it later) and am running into a problem with naming my variables:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim keylength As Double = TrackBar1.Value
Dim baseloop As Double = 1
Dim charpos As Double = 1
Do While baseloop < keylength
Randomize()
Dim name As String = "num" & charpos
Dim (name) As Integer = CInt(Int((62 * Rnd()) + 1))
'I would like to name this variable the current value of the variable "name".
baseloop = baseloop + 1
charpos = charpos + 1
Loop
End Sub
The end result should be random doubles (as many as TrackBar1.Value) containing random doubles from 1-62 and named num1, num2, num3, etc.... Then I can replace all the 1s with a, 2 with b, etc etc....
Thanks for your help
As has been said, what you claim to want to do is not possible. You can't declare an arbitrary number of variables at run time because variables are declared at design time. If you want to store an arbitrary number of values then you declare one variable and assign to that variable an array or collection of some sort. An array can be created with any size at run time and collections can grow to an arbitrary size at run time. Basically, what you're trying to do is outright wrong.
If you want an arbitrary number of Double values then create an array with a sized based on a user-defined value and then simply loop to populate it, e.g.
Dim values(userDefinedValue - 1) As Double
For i = 0 To values.GetUpperBound(0)
'...
Next
You then access the values by index. The first value is at index 0, the second at index 1, ..., the last at index GetUpperBound(0).
I have some VB code that gives me a random number, 1 between 20 (X). However, within 20 attempts, I will get the same number twice. How can I get a sequence of random numbers without any of them repeating? I basically want 1-20 to show up up in a random order if I click a button 20 times.
Randomize()
' Gen random value
value = CInt(Int((X.Count * Rnd())))
If value = OldValue Then
Do While value = OldValue
value = CInt(Int((X.Count * Rnd())))
Loop
End If
For 1 to 20, use a data structure like a LinkedList which holds numbers 1 to 20. Choose an index from 1 to 20 at random, take the number at that index, then pop out the number in that location of the LinkedList. Each successive iteration will choose an index from 1 to 19, pop, then 1 to 18, pop, etc. until you are left with index 1 to 1 and the last item is the last random number. Sorry for no code but you should get it.
The concept is, you have to add the generated random number into a list, and before adding it into the list, make sure that the new number is not contains in it. Try this code,
Dim xGenerator As System.Random = New System.Random()
Dim xTemp As Integer = 0
Dim xRndNo As New List(Of Integer)
While Not xRndNo.Count = 20
xTemp = xGenerator.Next(1, 21)
If xRndNo.Contains(xTemp) Then
Continue While
Else
xRndNo.Add(xTemp)
End If
End While
[Note: Tested with IDE]
for that purpose, you need to store all previous generated number, not just one, as u did in OldValue named variable. so, store all previously generated numbers somewhere (list). and compare the newly generated number with all those in list, inside ur while loop, and keep generating numbers, while number is not equal to any of one in list..
Add the numbers to a list and then pick them in a random order, deleting them as they are picked.
Dim prng As New Random
Dim randno As New List(Of Integer)
Private Sub Button1_Click(sender As Object, _
e As EventArgs) Handles Button1.Click
If randno.Count = 0 Then
Debug.WriteLine("new")
randno = Enumerable.Range(1, 20).ToList 'add 1 to 20 to list
End If
Dim idx As Integer = prng.Next(0, randno.Count) 'pick a number
Debug.WriteLine(randno(idx)) 'show it
randno.RemoveAt(idx) 'remove it
End Sub
So i am trying to make a search bot that uses random words. I am using an increment value with Minimum of 2 and a Maximum of 30 for the number of searches to do at a time.
I was thinking something like this but it also seems like it would not be as good since it would not really generate a random string which would be a lot better:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim SE As String
SE = NumericUpDown1.Value
Select Case SE
Case "2"
End Select
End Sub
If anybody could help me It would be greatly appreciated.
You can use the Random class and it's method Next to create random numbers.
Dim rnd As New Random()
Dim SE As String = rnd.Next(2, 31).ToString()
Note that the random number generation starts from a seed value. If the same
seed is used repeatedly, the same series of numbers is generated.
So if you want to use a loop, you should not create the random instance in the loop but outside of it.
However, i'm not sure what kind of words you want to create. I doubt that you want numeric strings between "2" and"30" even if your code suggests it.
Update according to your comment
The 2 and 30 are how many searches to do at a time, i want to
randomize the word(s) out of
lets say a list of 60-70 words
So i assume that you want a random number(between 2-30)of random words from a list of strings:
Dim words = {"word 1", "word 2", "word 3", ".....", "word 60"}
Dim rnd As New Random()
Dim howMany As Int32 = rnd.Next(2, 31)
Dim randomWords As New List(Of String)
For i As Int32 = 1 To howMany
Dim nextRandomIndex = rnd.Next(0, words.Count)
randomWords.Add(words(nextRandomIndex))
Next