Friends I have a serious issue at present and Honestly I have no idea as to why this isn't working as expected. I am more a custom to C# than VB can anyone help with the following Code Example
Please note that the String is passed from other classes and cannot be altered
The string arrL = "Someone#Something,200,First,50.00,60,Second,60.00,20,Third,70.00,120"
E.G where "Someone" is User, "Something" is an ID, "200" is Totaltime then frequency name "First" then frequency of "50.00" then its Time to run e.g 60 seconds. then next Item and so on.
Dim Sequence As New ArrayList
Sequence.AddRange(arrL.Split(","))
If Sequence.Count > 0 Then
RunFreq.ClientName = Sequence(0).ToString.Split("#")(0)
RunFreq.ClientProgramName = Sequence(0).ToString.Split("#")(1)
RunFreq.ClientProtocolTotalTime = Sequence(1).ToString
For i As Integer = 2 To Sequence.Count - 1
Dim g() = Sequence(i).ToString().Split(",")
Dim b As New ClassWave.ClassFrequency
b.Name = g(0) 'Here i get a Value
b.Frequency = CDbl(g(1)) '< HERE I get Index was outside the bounds of the array.
b.Time = CInt(g(2)) ' Same here Index was outside the bounds of the array.
Next
End If
I get Index Outside Bounds on g(1) and g(2) instead of 50.00 and 60. Any Ideas?
Preliminaries: You should turn on Option Strict, and consider using a List(of String) in place of the ArrayList.
Your second line, splits the string by "," into Sequence, so there is no need to split it again - you get the error because they cant be split further (and you didnt check the count). This works:
Dim arrl As String = "Someone#Something,200,First,50.00,60,Second,60.00,20,Third,70.00,120"
Dim Sequence As New ArrayList
Sequence.AddRange(arrl.Split(","c))
Dim a, b, c As String
If Sequence.Count > 0 Then
a = Sequence(0).ToString.Split("#"c)(0)
b = Sequence(0).ToString.Split("#"c)(1)
c = Sequence(1).ToString
Console.WriteLine("{0} - {1} - {2}", a, b, c)
For i As Integer = 2 To Sequence.Count - 1 Step 3
a = Sequence(i + 0).ToString
b = Sequence(i + 1).ToString
c = Sequence(i + 2).ToString
Console.WriteLine("{0} - {1} - {2}", a, b, c)
Next
End If
You could also use this for the split:
Sequence.AddRange(arrl.Split("#"c, ","c))
This would create 12 elements in the ArrayList, but since the first 3 parts go elsewhere, that doesnt have as much value.
Output:
Someone - Something - 200
First - 50.00 - 60
Second - 60.00 - 20
Third - 70.00 - 120
Note that .ToString() is required when fetching from the ArrayList because it is not typed - it only ever contains Object. A List(of String) would store the parts as string.
Related
I have a list
Dim list As New List(Of Double)
I want to remove the last entries, if the differences are > 20.
My idea to check the last 30 entries:
Do While index >= list.Count - 30
If Math.Sqrt((list(index) - list(index + 1)) ^ 2) > 20 Then
list.RemoveAt(index)
Exit Do
End If
Loop
It does not lead to my solution. Can somebody help? Thank you very much.
Instead of using a List of doubles I would use a LinkedList of doubles to make use of the class methods and properties like AddFirst, Last, Last.Previous
So let's assume that you have a LinkedList declared like
Dim list As New LinkedList(Of Double)
And you have added elements to this list using
list.AddFirst(134.5678)
Now, you could remove from the end of the list with something like this
' You want to have a list of at least 30 elements
Do While list.Count > 30
' Last node and the previous one
Dim dLast = list.Last
Dim dLastPrev = list.Last.Previous
' Evaluate the two elements
If Math.Sqrt(dLastPrev.Value - dLast.Value) ^ 2 > 20 Then
' Remove the last and continue to evaluate the next pair
list.RemoveLast()
Else
' Stop if the condition is not met.
Exit Do
End If
Loop
Of course this could also be done using your current list type.
Also notice how I have swapped the two elements to verify. This is done to avoid any possibility of an IndexOutOfRangeException
Dim index as Integer = list.Count - 1
Do While index >= list.Count - 30
Dim prev = index - 1
If Math.Sqrt((list(prev) - list(index)) ^ 2) > 20 Then
list.RemoveAt(index)
else
Exit Do
End If
index = index - 1
Loop
I want fill my combobox with time values like (08:00, 08:10, 08:20 until 09:50) step=10 minutes but the result is like (8:00, 8:10, 8:20, 8:30, 9:-20,9:-10, 9:00, 9:10, 9:20).
My code doesn't show the value like 8:40, 8:50 and he also show negative value like 9:-20, 9:-10).
So please how can I resolve this problem?
Heure_rdv.Items.Clear()
Dim nbr_minute2 As String
For i = 480 To 590 Step 10
Dim nbr_heure As Integer = cint(i / 60)
Dim nbr_minute As Integer = (i - (nbr_heure * 60))
nbr_minute2 = CStr(nbr_minute) + "0"
If ((i - (nbr_heure * 60)) = 0) Then
Heure_rdv.Items.Add(CStr(nbr_heure) + ":" + nbr_minute2)
Else
Heure_rdv.Items.Add(CStr(nbr_heure) + ":" + CStr(nbr_minute))
End If
Next
This is how I should do try it in VBA.
Should be similar in VB.NET
DIM i As Integer 'Counter 1
Dim ii As Integer 'Counter 2
' make 1st loop for hours
for i = 8 To 9
' mkae 2nd loop for minutes
for ii = 0 To 50 Step 10
'
Heure_rdv.Items.Add(i & ":" & ii)
next
next
This could be done with fewer lines of code using linq
Dim steps = Enumerable.Range(0,6)
Dim items as List(Of String) = new List(Of String)()
items.AddRange(steps.Select(Function(x) "08:" & (x * 10).ToString("D2")))
items.AddRange(steps.Select(Function(x) "09:" & (x * 10).ToString("D2")))
Heure_rdv.DataSource = items
First we create a list of integers from 0 to 5 (6 elements), then using these elements we create the strings required multiplying each element of the integer list by ten and converting the result to a two digit string. We do this one time for the 8 hour and one time for the 9. Finally we could set the combo datasource to the resulting list of strings.
I am trying, for several days, to take specifically ordered data from a .txt file and then convert and store it to double or string arrays
the data is stored in the file in this way:
1 0 1 0 >= 15
0 1 0 1 >= 28
1 1 0 0 <= 30
0 0 3 1 <= 22
-1 0 2 0 <= 0
(one line after the other with no blank lines between them)
and my code for this goes like:
Using stream As System.IO.FileStream = System.IO.File.OpenRead("C:\Users\user\Desktop\test_new.txt")
Using reader As New System.IO.StreamReader(stream)
Dim lineCount = File.ReadAllLines("C:\Users\user\Desktop\test_new.txt").Length
Dim line As String = reader.ReadLine()
Dim aryTextFile() As String
Dim operator1() As String
Dim variables(,) As Double
Dim results() As Double
Dim counter3 As Integer
counter3 = 0
NRows = lineCount
While (line IsNot Nothing)
Dim columns = line.Split(" ")
aryTextFile = line.Split(" ")
line = reader.ReadLine()
NVars = columns.Length - 3
For j = 0 To UBound(aryTextFile) - 3
variables(counter3, j) = CDbl(aryTextFile(j))
Next j
For j = NVars To UBound(aryTextFile) - 2
operator1(counter3) = CStr(aryTextFile(j))
Next j
For j = UBound(aryTextFile) - 2 To UBound(aryTextFile) - 1
results(counter3) = CDbl(aryTextFile(j))
Next j
counter3 = counter3 + 1
End While
End Using
End Using
I'm getting warnings which result in errors ofc.
Variable 'variables' is used before it has been assigned a value. A null reference exception could result at
runtime. C:\Users\user\Documents\Visual Studio
2008\Projects\WindowsApplication1\WindowsApplication1\Form1.vb 230 25 WindowsApplication1
Variable 'operator1' is used before it has been assigned a value. A null reference exception could result at
runtime. C:\Users\user\Documents\Visual Studio
2008\Projects\WindowsApplication1\WindowsApplication1\Form1.vb 236 25 WindowsApplication1
Variable 'results' is used before it has been assigned a value. A null reference exception could result at
runtime. C:\Users\user\Documents\Visual Studio
2008\Projects\WindowsApplication1\WindowsApplication1\Form1.vb 243 25 WindowsApplication1
So what am I doing wrong and how can I fix it
note: data is saved from dynamic matrixes, so it can be a lot bigger than the displayed example (several lines with several columns), and that is the reason I'm trying to program it, in order to save me some lab time of copying and pasting it manually...
thanks in advance,
Viktor
p.s. if another member or admin can indicate an older post about my question, that would also be very helpful, but I am reading posts for the last 4 days in similar questions and I couldn't find something working for me
p.s.2 since is my first post, I have also tried to attach the project and I couldn't find a way :)
You need to define the dimensions of your arrays before trying to use them.
If you don't know what the size will be use a list instead.
'No defined size - Warning
Dim array1() As String
'Error when trying to access
array1(4) = "Testing"
'Defined size
Dim array2(10) As String
array2(5) = "Testing"
I am trying to build a random sample and random assignment generator for a website I am working on that is supposed to assign randomly selected items in an equal number to a variable set of people.
For example:
In this round of assessment, we have 9 assessors, and 477 items that need to be graded by two assessors each (with the same assessor not grading the same item twice). This would come out to 954 total "assessments" that need to be made, and 106 per assessor.
Therefore I'd need an eventual list like...
(Item, Assessor1, Assessor2)
(1, A, B)
(2, C, D)
(3, E, F)
(4, G, H)
(5, H, B)
(6, B, F)
.
.
.
And so on
I've found websites that can do random number generation and even some that can do random assignment over groups, but even then I am still finding situations where the same assessor will be grading the same item throughout the results.
I am less concerned about the inherent randomness and more concerned about making sure each result list has every assessor grading the same number of items without grading the same one.
I can usually get it to the point where I have it -close- and maybe one grader will be 1 or 2 more and another will be 1 or 2 less, but unfortunately it's a hard requirement that they be equal groupings.
EDIT
Implemented #Tinstaafl's code and ran the following:
Dim col As New MyItemCollection
col.AddAssessor("A")
col.AddAssessor("B")
col.AddAssessor("C")
col.AddAssessor("D")
col.AddAssessor("E")
col.AddAssessor("F")
col.AddAssessor("G")
col.AddAssessor("H")
col.AddAssessor("I")
For I As Integer = 1 To 477
col.AddItem(I.ToString)
Next
Dim newList As List(Of MyItemCollection.MyItem) = col.AssignAssessors
For Each item As MyItemCollection.MyItem In col.itemlist
Response.Write(item.ToString & "<br/>")
Next
Unfortunately my output looks like
1 - F - F
2 - I - I
3 - E - E
4 - F - F
5 - C - C
6 - D - D
7 - G - G
8 - A - A
9 - C - C
10 - B - B
11 - D - D
12 - D - D
13 - D - D
14 - D - D
15 - H - H
And so on...
One idea that I can think of is as follows:
Shuffle the assessors {1-9}. Then assign the first 4.5 items to them sequentially as per the result of this shuffle.
Then shuffle them again. Again assign them sequentially to the next items. If the first assessor happens to be the same one that is already assigned to the 5th item, then swap the 1st and second assessor in the list.
Keep doing this for all items.
One way is with a collection class and embedded classes for the items and assessors. Here's a partial implementation to show how the list could be generated:
Public Class MyItemCollection
Class Assessor
Public Name As String = ""
Public Shared Operator <>(LH As Assessor, RH As Assessor) As Boolean
Return LH.Name <> RH.Name
End Operator
Public Shared Operator =(LH As Assessor, RH As Assessor) As Boolean
Return RH.Name = LH.Name
End Operator
Public Overrides Function ToString() As String
Return Name
End Function
End Class
Class MyItem
Public Name As String = ""
Public Assessor1 As New Assessor
Public Assessor2 As New Assessor
Public Overrides Function ToString() As String
Return Name & " - " & Assessor1.ToString & " - " & Assessor2.ToString
End Function
End Class
Private AssessorList As New List(Of Assessor)
Private ItemList As New List(Of MyItem)
Public Sub AddAssessor(Name As String)
AssessorList.Add(New Assessor With {.Name = Name})
End Sub
Public Sub AddItem(Name As String)
ItemList.Add(New MyItem With {.Name = Name})
End Sub
Private Rnd As New Random(Now.Millisecond * Now.Day * Now.Minute)
Public Function AssignAssessors() As List(Of MyItem)
Dim OutVal As New List(Of MyItem)
Dim average As Integer = ((ItemList.Count \ AssessorList.Count) * 2) + 5
Dim AssessorCount(AssessorList.Count - 1) As Integer
For Each item As MyItem In ItemList
Dim firstassessorindex As Integer
Do
firstassessorindex = Rnd.Next(0, AssessorList.Count)
Loop Until AssessorCount(firstassessorindex) <= average
item.Assessor1 = AssessorList(firstassessorindex)
AssessorCount(firstassessorindex) += 1
Dim secondassessorindex As Integer
Do
secondassessorindex = Rnd.Next(0, AssessorList.Count)
Loop Until AssessorList(secondassessorindex) <> item.Assessor1 AndAlso AssessorCount(secondassessorindex) < average
item.Assessor2 = AssessorList(secondassessorindex)
AssessorCount(secondassessorindex) += 1
Next
OutVal = ItemList
Return OutVal
End Function
End Class
One thing that wasn't clear in your explanation was if the distribution between Assessor1 and Assessor2 is important(does it matter if an assessor is the second assessor more times than it is the first?). If you need that, then a List(Of Tuple(Integer, Integer)) might be needed for the AssessorCount instead of a List(Of Integer)
The ToString method for each item in the return list will be in the format -
ItemName - Assessor1Name - Assessor2Name
I'm not sure if I understand your assignment rules, but this might be close.
var assessors = new []
{
"A", "B", "C",
"D", "E", "F",
"G", "H", "I",
};
var rnd = new Random();
var query =
from a1 in assessors
from a2 in assessors
where a1 != a2
orderby rnd.Next()
select new { a1, a2};
var results =
Enumerable
.Range(1, 477)
.Zip(query
.Repeat(),
(i, aa) => new
{
Item = i,
Assessor1 = aa.a1,
Assessor2 = aa.a2,
});
I get this kind of result:
1 F B
2 E C
3 D H
...
476 F C
477 B E
I am developing an application using Visual Basic 2010 for hydraulic calculations of a pipe network.
This application uses a lot of iterations and loops, depending on the user input and size of network. Most of the results have to be saved temporarily to be used for the next step of calculations.
Firstly, I used a DataGridView to save the results but as the number of iterations increased, the application became very slow.
Now I am trying to create a DataTable, then populate it with some initial results (this part was successful). The obtained DataTable has some columns that are not populated like so:
22 24 10
3 16 22 9 15
16 12 24 13
14 21 10 23 12 1
24 18 23 2 1
Other calculations are performed and a certain value (X) is obtained.
Now I am trying to loop through the columns of a specific row to check if the calculated value (X) equals to one of the values in those columns.
My question is: How can I loop through only the columns that have values (avoiding the columns containing NULL values) for a specific row?
I am a beginner in VB.net. I hope my question is clear as I didn't provide any code.
Thanks in advance for you help.
This is the initial code I used:
Results.DGVInitial.Rows.Clear()
Results.DGVFinal.Rows.Clear()
For m As Integer = 0 To NetworkLayout.DGVNetworkLayout.Rows.Count - 1
Results.DGVInitial.Rows.Add()
Next
Dim I As Integer = NetworkLayout.DGVNetworkLayout.Rows.Count - 1
Dim Sec(I), Ini(I) As Integer
Dim Hyd(I), Dia(I), Len(I) As Single
Dim Qsec(I), Qini(I), Vsec(I) As Single
Dim U(I), Y(I) As Single
Do
I = I - 1
Sec(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(0).Value
Ini(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(1).Value
Hyd(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(6).Value
Dia(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(4).Value
Len(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(3).Value
Dim V As Integer
V = Results.DGVRandomGen.Rows(TotalNum_Runs - 1).Cells(I).Value
Qsec(I) = 0
Dim q As Single = 0
For n As Integer = 0 To Results.DGVInitial.Rows.Count - 1
If Results.DGVInitial.Rows(n).Cells(1).Value = Sec(I) Then
q = Results.DGVInitial.Rows(n).Cells(0).Value
Qsec(I) = Qsec(I) + q
Else
Qsec(I) = Qsec(I)
End If
Next
If V = 1 Then ' if the hydrant is open
Qini(I) = Hyd(I) + Qsec(I)
Else ' if the hydrant is close
Qini(I) = Qsec(I)
End If
Results.DGVInitial.Rows(I).Cells(0).Value = Qini(I)
Results.DGVInitial.Rows(I).Cells(1).Value = Ini(I)
Results.DGVSectionDischarges.Rows(TotalNum_Runs - 1).Cells(I).Value = ini(I).ToString("F2")
Now instead of using
V = Results.DGVRandomGen.Rows(TotalNum_Runs - 1).Cells(I).Value
I would like to replace the "DGVRandomGen" with a DataTable called "DT_Random"
Like I said I am a beginner so I am not sure how to code it but it will be something like this:
For DT_Random.Rows (TotalNum_Runs - 1)
For Each col As DataColumn In DT_Random.Columns
If DT_Random.Rows(TotalNum_Runs - 1).Item(col) = I Then
Qini(I) = Hyd(I) + Qsec(I)
Else
Qini(I) = Qsec(I)
End If
Next
But I want to avoid Null values as not all columns are populated
Thanks
Maybe this will help you:
Dim myXvalue = 24
Dim myDataTable As New DataTable
myDataTable.Columns.Add("Col1")
myDataTable.Columns.Add("Col2")
myDataTable.Columns.Add("Col3")
myDataTable.Columns.Add("Col4")
myDataTable.Rows.Add(22, 24, 10, DBNull.Value)
myDataTable.Rows.Add(3, 16, 22, DBNull.Value)
myDataTable.Rows.Add(24, 18, DBNull.Value, 24)
For Each column As DataColumn In myDataTable.Columns
If IsDBNull(myDataTable.Rows(0).Item(column)) Then
MsgBox("DB Null Found At: " & column.ColumnName)
Continue For
End If
If myDataTable.Rows(0).Item(column) = myXvalue Then
MsgBox("Match: " & myDataTable.Rows(0).Item(column) & " found at " & column.ColumnName)
End If
Next column
Just a quick example, you may need to restructure it a bit, but at least it shows you how to access the values in your datatable by columns. I would do a function that passes a row index as a parameter and returns a boolean. Create two booleans inside the sub, one for dbnull existing in the row, and one for finding a matching value. If dbnull bool is false, and match value is true, then return true. Just make sure you loop all the columns and dont exit early.
If you need me to elaborate let me know.