Hello I'm trying to develop a Linq query to find the Lowest Unique Value or Lowest Value also sorted by Row and Column Value.
First it does the Lowest Unique Value Exact match (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 or not found).
Table of Data
Row | Column | Value |
---|---|---|
1 | 1 | 2 |
0 | 2 | 3 |
0 | 2 | 2 |
The output should be the last data in the table 0,2,2
since it has the lowest Row and it's a duplicate Value (row 1 and row 0).
if you add Data 2,0,0
(Value of 0) would overrule the duplicate Values (2's
).
Row | Column | Value |
---|---|---|
1 | 1 | 2 |
0 | 2 | 3 |
0 | 2 | 2 |
2 | 0 | 0 |
Structure FoundValue
Dim Value As Short
Dim Row As Integer
Dim Column As Integer
End Structure
Dim UniqueValuesFound As New List(Of Short)
Dim ValuesFoundInPath As New List(Of FoundValue)
UniqueValuesFound.Add(0)
UniqueValuesFound.Add(2)
UniqueValuesFound.Add(3)
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)
'New Attempt
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)
'New Attempt
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)
Look at 'New Attempt
code it speaks itself, what I'm trying to do is find the first value which has a exact match in UniqueValuesFound
and if it cannot find the value in UniqueValuesFound
array then default to spitting out a partial match lowest value it can find. The array ValuesFoundInPath
contains all the values in a random order as well as Column and Row types, which have to be sorted for partial match to find the lowest Row first.
CodePudding user response:
I have finally Solved It!, needed to use Find
instead of Where
and problem disappeared!.
The answer now requires 2 linq queries instead of one cannot do chaining on Find
ValuesFoundInPath = ValuesFoundInPath.OrderBy(Function(p) p.Value).ThenBy(Function(p) p.Row).ThenBy(Function(p) p.Column).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.