Hello I'm trying to develop a Linq query to find the Lowest Unique Value or else Lowest Value which is also sorted by Row and Column Value. First it does the Lowest Unique Value Exact match using BinarySearch (unique value) If nothing is found then it does a Partial Match (lowest value then lowest row then column) Whichever has the smallest Value is the output (unique (smallest first)) or (not found (smallest second or first if unique not found)).
Console returns this value
2,0,0
When it should be
2,1,1
Private Sub Button11_Click(sender As Object, e As EventArgs) Handles Button11.Click
Dim UniqueValuesFound As New List(Of Short)
Dim ValuesFoundInPath As New List(Of FoundValue)
UniqueValuesFound.Add(1)
'UniqueValuesFound.Add(0)
'UniqueValuesFound.Add(2)
'UniqueValuesFound.Add(3)
UniqueValuesFound = UniqueValuesFound.Distinct().ToList()
UniqueValuesFound.Sort()
Dim foundValue As New FoundValue
foundValue.Value = 2
foundValue.Row = 1
foundValue.Column = 1
ValuesFoundInPath.Add(foundValue)
'foundValue = New FoundValue
'foundValue.Value = 3
'foundValue.Row = 0
'foundValue.Column = 2
'ValuesFoundInPath.Add(foundValue)
'foundValue = New FoundValue
'foundValue.Value = 2
'foundValue.Row = 0
'foundValue.Column = 2
'ValuesFoundInPath.Add(foundValue)
'foundValue = New FoundValue
'foundValue.Value = 0
'foundValue.Row = 2
'foundValue.Column = 0
'ValuesFoundInPath.Add(foundValue)
Dim alreadyFound As Boolean = False
Dim matching = ValuesFoundInPath.Where(Function(s)
Dim index As Integer = UniqueValuesFound.BinarySearch(s.Value)
If alreadyFound = False AndAlso index >= 0 Then
alreadyFound = True
Return True 'UniqueValuesFound(index) 'exact match
ElseIf alreadyFound = False AndAlso index < 0 Then
alreadyFound = True
Return True 's.Value
Else
Return False
End If
End Function).OrderBy(Function(p) p.Value).ThenBy(Function(p) p.Row).ThenBy(Function(p) p.Column)
Console.WriteLine(matching(0).Value.ToString & "," & matching(0).Row.ToString & "," & matching(0).Column.ToString)
End Sub
CodePudding user response:
Solved it, needed to use Find
instead of Where
and problem disappeared!.
The answer now reqires 2 linq queries instead of one cannot do chaining on Find
ValuesFoundInPath = ValuesFoundInPath.OrderBy(Function(p) p.Row).ThenBy(Function(p) p.Column).ThenBy(Function(p) p.Value).ToList()
Dim alreadyFound As Boolean = False
Dim matching = ValuesFoundInPath.Find(Function(s)
Dim index As Integer = UniqueValuesFound.BinarySearch(s.Value)
If alreadyFound = False AndAlso index >= 0 Then
alreadyFound = True
Return True 'UniqueValuesFound(index) 'exact match
ElseIf alreadyFound = False AndAlso index < 0 Then
alreadyFound = True
Return True 's.Value
Else
Return False
End If
End Function)
Dim result As New Result
result.Answer = matching.Value
result.CurrentRow = matching.Row
result.CurrentColumn = matching.Column
You may have problems since Find(...)
pre-sorts the list of values always. So you need to use FindIndex(...)
this avoids the sorting issue.
Dim matchingIndex = ValuesFoundInPath.FindIndex(Function(s)
Dim index As Integer = UniqueValuesFound.BinarySearch(s.Value)
If alreadyFound = False AndAlso index >= 0 Then
alreadyFound = True
Return True 'UniqueValuesFound(index) 'exact match
ElseIf alreadyFound = False AndAlso index < 0 Then
alreadyFound = True
Return True 's.Value
End If
Return False 'No match.
End Function)
If matchingIndex < 0 Then MessageBox.Show("Wtf!")
Dim result As New Result
result.Answer = ValuesFoundInPath(matchingIndex).Value
result.CurrentRow = ValuesFoundInPath(matchingIndex).Row
result.CurrentColumn = ValuesFoundInPath(matchingIndex).Column
It makes the OrderBy(...)
useless because Find(...)
pre-sorts the lists by incrementing values.