excluding X number of lines while building a string in a Loop

coder4life

Member
Joined
Sep 25, 2013
Messages
9
Programming Experience
1-3
I have to reconcile 2 columns of data that are built using a loop

Typically, the loop just gets everything fed into it. if incoming data had 50 lines, the loop will record them all

eg

VB.NET:
     Do While some.condition

string = string & Environment.NewLine

Loop

however, i dont want to begin building that string until the Xth line, or i might not want the last X lines

lets say the incoming data has 50 lines (but i wont know exactly). but i do know i want to pass on the first X lines and *then* begin to build the string

eg

incoming is

100
200
125
500
490
222
326
777


if i fed this into the loop the normal result would be:

100
200
125
500
490
222
326
777


but lets say i do not want the first 3 to be recorded. so when i run the loop, i have some code that records everything after the first 3 lines, so the result will be:

500
490
222
326
777


And the same for the end of the string built by the loop
but for the *last* X number of lines. so if i dont want the *last* 3 instead of:

100
200
125
500
490
222
326
777


i will get

100
200
125
500
490




so what i have now are two strings, or they can be two sets of integers (preferable) that are in sync with each other, wherein i can do a little math:

500 - 100
490 - 200
222 - 125
326 - 500
777 - 490
 
Hi,

You can use the LINQ Methods Skip and Take to achieve this. Have a play with this:-

Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
  Dim myNumbers() As Integer = {100, 200, 300, 400, 500, 600, 700, 800, 900}
  Dim startNumbers() As Integer = myNumbers.Take(5).ToArray
  Dim endNumbers() As Integer = myNumbers.Skip(3).ToArray
 
  MsgBox(String.Join(Environment.NewLine, startNumbers))
  MsgBox(String.Join(Environment.NewLine, endNumbers))
End Sub


Hope that helps.

Cheers,

Ian

[Edit]

I have just seen that you have already asked this on another Forum. So, on the basis that I have given exactly the same sort of answer as you got on that forum, what are you not understanding with what you have already been told?
 
Last edited:
the only issue is the dataset is built in the loop as a string. How can I build that dataset inside the loop where the result will be an integer?

VB.NET:
Dim n as integer

do while some.condition 

n = ???

(need code to build integer from the incoming data feed)

Loop

so what is built in the loop is the `myNumbers` data inside the brackets in your code that will survive outside the loop

I.e.

Dim mynumbers() as integer = {n}
 
it is an api that calls data from a server from the trading floor.

the data feeds into a loop.

i am customizing the prog. so what i am doing is trying to redirect the data to serve my custom purpose

when the prices are reqwuested from the server, they are fed one line at a time inside a 'do while' loop

the question is how to capture all the data (a fixed set of prices for a certain time frame) so i can then plug that data set into your code to represent the set of numbers you have spelled out, but in reality they come from the server inside the do while loop.

i want to capture that data, place in a variable i can work with outside the loop, just as in the example we are discussing now


thanks for the reply
 
OK,

Whilst I cannot replicate any data coming in from a server through an API I can simulate that sort of thing with a Timer. So, have a look at this example which simulates two numbers coming into your application in the form of a string like "1234 5678":-

Public Class Form1
  'This is a Private DataStream Class to hold all the Information received from the Trading Floor
  Private Class DataStream
    Public Property TimeReceived As DateTime
    Public Property FirstNumber As Integer
    Public Property SecondNumber As Integer
 
    Public Sub New()
    End Sub
 
    Public Sub New(ByVal tReceived As DateTime, ByVal fNumber As Integer, ByVal sNumber As Integer)
      TimeReceived = tReceived
      FirstNumber = fNumber
      SecondNumber = sNumber
    End Sub
  End Class
 
  'This can be ignored and is just used to generate data in the Timer
  Dim myRandom As New Random
 
  'This is the IMPORTANT bit to remember. This list is created at the CLASS Level
  'So that it can be accessed from any routine with this Parent Class
  Dim myFloorDataList As New List(Of DataStream)
 
  'This is the simulation of the incoming Data Stream through the API
  Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
    'Read the Data From the API
    Dim myDataStream As String = String.Format("{0} {1}", myRandom.Next(1000, 9999), myRandom.Next(1000, 9999))
 
    'Split the data stream by the space character into two strings 
    Dim myNumberString() As String = myDataStream.Split(" "c)
 
    Dim fNumber As Integer
    Dim sNumber As Integer
 
    'Use TryParse to validate the string and convert to integers.
    'we can then create a new instace of our DataStreamn class and add that to the
    'FloorDataList
    If Integer.TryParse(myNumberString(0), fNumber) AndAlso Integer.TryParse(myNumberString(1), sNumber) Then
      Dim myFloorData As New DataStream(Now, fNumber, sNumber)
      myFloorDataList.Add(myFloorData)
    End If
  End Sub
 
  Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    'Get some arbitrary start and end time to do some analysis on the data received
    Dim analysisStartTime As DateTime = Now.AddMinutes(-5)
    Dim analysisEndTime As DateTime = Now
 
    'Make a list of the first and second numbers based on the start and end time
    Dim listOfFirstNumbers As List(Of Integer) = myFloorDataList.Where(Function(x) x.TimeReceived >= analysisStartTime AndAlso x.TimeReceived <= analysisEndTime).Select(Function(x) x.FirstNumber).ToList
    Dim listOfSecondNumbers As List(Of Integer) = myFloorDataList.Where(Function(x) x.TimeReceived >= analysisStartTime AndAlso x.TimeReceived <= analysisEndTime).Select(Function(x) x.SecondNumber).ToList
 
    'Now we can use Take or Skip to get whatever data you need into the lists
    listOfFirstNumbers = listOfFirstNumbers.Take(5).ToList
    listOfSecondNumbers = listOfSecondNumbers.Skip(listOfSecondNumbers.Count - 5).ToList
 
    'We now have two lists of numbers with 5 elements that can be iterated through to do what you need
    For elementCount As Integer = 0 To listOfFirstNumbers.Count - 1
      MsgBox(String.Format("First Element is :{0}, and the Second Element is:{1}", listOfFirstNumbers(elementCount), listOfSecondNumbers(elementCount)))
    Next
  End Sub
End Class


Form this example you should be able to see how you can save your Data coming from the API into a List and then Query that List using the LINQ Where clause method and then Take or Skip the Elements that you need to perform your custom analysis.

The one thing that I would add is that if you must continue to use your Do While loop to continuously get Data from your API then I would suggest that you put this on a Back Ground thread so that you do not tie up the UI Thread. The reason why my example works is because the Timer fires on another Thread so the UI Thread is not tied up when wanting to do some analysis.

Hope that helps.

Cheers,

Ian
 
That was a little complicated for me and I was not able to integrate it into my code -- yet. i came up with a work around where now i have 2 strings where the average in one matches the high in the other.

i just need to figure out how to join them together, and then do the math.

the High string has this

15428
15433
15424
15423
15429
15438
15432
15434
15428
15437
15446

The Average string has this:

15425
15426
15431
15435
15440
15446
15451
15455
15459
15464
15468



what i want to do is join them together, or read row 1 of High and compare it with row 1 of Average

example

if row 1 of High (15428) is <= row 1 of Average (15425) then enter 1, else enter 0, and save it to an array

the results would be

0
0
1
1
1
1
1
1
1
1
1
 
First off string concat for that purpose is atrocious. What happens when the string gets huge and you keep trying to concat? Eventually the app will choke out.

Why don't you tell us a bit more about what you intend to do with the data? My guess is you would be better served storing each integer (you insist on string, but that is not what it really is is it? I see integers...) separately in a list. And then do whatever it is you want to do. If you only need to keep the most recent data, then use a Queue instead, and dequeue older data after n number.

More info will certainly help us (and you) understand the problem better...
 
Here is a simple example...

Always treat data for what it is, not how it is represented.

Class MyApp
    ' Simple type to hold the pairs
    Private Class ValuePair
        Public Property HighValue As Integer
        Public Property AverageValue As Integer
    End Class

    ' SourceList
    Private SourceList As New List(Of ValuePair)
    Private ResultsList As New List(Of Integer)
    
    Public Sub Main()
        ' You would populate your list here, from whatever source you have
        ' You add ValuePair objects into the SourceList
        For Each SourceObject In Whatever ' Replace with actual source...
            SourceList.Add(New ValuePair With {.HighValue = 15428, .AverageValue = 15425})
        Next
    
        ' And here you process the list. This works well if the source is a static file.
        ' Not so well if the source is a constant stream, there are better ways to deal with those.
        For Each vp As ValuePair In ValuePairList
            ResultsList.Add(If(vp.HighValue <= vp.AverageValue, 1, 0))
        Next
    End Sub
    
End Class
 
Back
Top