I have got a list of Strings looking like this:
The items of the list of Strings are formated like this "#,@" where # stands for an integer number and @ stands for a string or number.
I need to find the index of the first occurrence where the integer number is lower than the integer number of the previous item.
I am able to find it using a loop over all entries like this:
For X = 0 To UBound(TempList.ToArray) - 1
If Val(Left(TempList(X), InStr(TempList(X), ",") - 1)) > Val(Left(TempList(X 1), InStr(TempList(X 1), ",") - 1)) Then
Dim Result As String = TempList(X) & " -- " & TempList(X 1)
End If
Next
I am sure that this can be done much smarter using linq - but my very poor knowledge regarding linq is not enough ...
Can someone please give me a hint?
CodePudding user response:
Linq is cool but it is not necessarily faster. It is looping internally.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim TempList As New List(Of String) From {"450,245.5", "510,1", "520,1", "703,1", "704,0", "705,0", "706,0", "901,1.244", "921,3", "1,1", "2,1", "3,0"}
Dim Result As String = ""
For i As Integer = 1 To TempList.Count - 1
If CInt(TempList(i).Split(","c)(0)) < CInt(TempList(i - 1).Split(","c)(0)) Then
Result = $"{TempList(i)} At index {i} -- {TempList(i - 1)}"
Exit For 'Stop looping when found
End If
Next
MessageBox.Show(Result)
End Sub
CodePudding user response:
You can use LINQ for the loop, but I do think a For / For Each
is sufficient - see Mary's answer.
But at least, you could use LINQ to parse your list into something other than strings to make it more manageable when it's used. This will decouple your code a bit and will make it clearer. I'll hold the pair of data in a Tuple(Of Double, String)
. If I knew the first item was distinct, I would use a Dictionary(Of Double, String)
.
So for fun, you can use TakeWhile
instead of a For / For Each
.
Dim TempList = { "450,245.5", "510,1", "520,1", "701,0", "702,0", "703,1", "704,0", "705,0", "706,0", "720,0", "901.2,455", "921,3", "1,1", "2,1", "3,0"}
Dim parsedList = TempList.
Select(Function(s) s.Split(","c)).
Select(Function(ss) (CDbl(ss(0)), ss(1)))
Dim lastValue As Double = Double.NaN
Dim index = parsedList.TakeWhile(
Function(t)
Dim result = Double.IsNaN(lastValue) OrElse t.Item1 > lastValue
lastValue = t.Item1
Return result
End Function).Count()
Dim item = parsedList(index)
Console.WriteLine($"Index: {index}, number: {item.Item1}, string: {item.Item2}")
Index: 12, number: 1, string: 1
This is basically just making a For Each
with LINQ. It's probably not necessary, and a simple loop is arguably more readable, and you won't gain any benefit in performance either.