我有以下课程:
Public Class Row
Public Sub New()
End Sub
Public Sub New(ByRef lookupTable As LookupTable)
myLookupTable = lookupTable
End Sub
Private myLookupTable As LookupTable
<XmlAttribute("value")> _
Public Property Value As Double
<XmlArray("values")> _
<XmlArrayItem("value")> _
Public Property Values As List(Of Double)
<XmlIgnore> _
Public ReadOnly Property LookupTable As LookupTable
Get
Return myLookupTable
End Get
End Property
End Class
我正在努力做到以下几点:
Dim yIndexBelow As Integer = Rows.IndexOf(Rows.Where(Function(row) row.Value <= yVal).Max())
Dim yIndexAbove As Integer = Rows.IndexOf(Rows.Where(Function(row) row.Value >= yVal).Min())
Dim yProportion As Double = (yVal - Rows(yIndexBelow).Value) / (Rows(yIndexAbove).Value - Rows(yIndexBelow).Value)
在第二行行 上,会抛出异常:At least one object must implement IComparable.
呃......什么?
从何时Double
未实现IComparable?很明显它确实如此。
更重要的是;为什么它只在第二个行失败?
任何想法?。
P.S。
如果您想知道,yVal
已设置。
答案 0 :(得分:2)
为了证明你的观点,这个课程就足够了
ggplot(df, aes(x = x)) +
geom_histogram(binwidth = .05, position = "dodge", color = "black", fill = "transparent") +
geom_vline(aes(xintercept = mean), linetype = "dashed", color = "red") +
theme_bw() +
scale_x_continuous(name="Values", expand = c(0, 0),
breaks = sort(c(seq(0,10,1), mean)),
labels = sort(c(0L:10L, round(mean, digits = 2))))
正如您所提到的,解决方案是实现IComparable。见https://support.microsoft.com/en-us/kb/320727
Public Class Row
Public Property Value As Double
End Class
测试用例仅需要索引查找部分。这是一个很好的例子。这应该使用上面Public Class Row
Implements IComparable(Of Row)
Public Property Value As Double
Public Function CompareTo(other As Row) As Integer _
Implements IComparable(Of Row).CompareTo
Return If(Me.Value > other.Value, 1, -1)
End Function
End Class
的两个版本进行测试。可以看出,当Row
没有实现IComparable时,第一部分可以工作,因为只有一个元素,正如你所指出的那样,但第二部分没有。简单地说,LINQ的Max函数只是短路比较,因为只有一个元素。
Row
Sub Main()
Dim yVal As Double = 6.7
Dim yIndexBelow As Integer
Dim yIndexAbove As Integer
Dim rows As New List(Of Row)()
rows.Add(New Row() With {.Value = 5})
yIndexBelow = rows.IndexOf(rows.Where(Function(row) row.Value <= yVal).Max())
yIndexAbove = rows.IndexOf(rows.Where(Function(row) row.Value >= yVal).Min())
Console.WriteLine("Rows: {0}",
String.Join(", ", rows.Select(Of Double)(Function(r) r.Value)))
Console.WriteLine("Index below {0}: {1}",
yIndexBelow, If(yIndexBelow = -1, "N/A", rows(yIndexBelow).Value))
Console.WriteLine("Index above {0}: {1}",
yIndexAbove, If(yIndexAbove = -1, "N/A", rows(yIndexAbove).Value))
rows.Add(New Row() With {.Value = 6})
rows.Add(New Row() With {.Value = 2})
rows.Add(New Row() With {.Value = 10})
rows.Add(New Row() With {.Value = -6})
rows.Add(New Row() With {.Value = 12})
rows.Add(New Row() With {.Value = 1})
yIndexBelow = rows.IndexOf(rows.Where(Function(row) row.Value <= yVal).Max())
yIndexAbove = rows.IndexOf(rows.Where(Function(row) row.Value >= yVal).Min())
Console.WriteLine("Rows: {0}",
String.Join(", ", rows.Select(Of Double)(Function(r) r.Value)))
Console.WriteLine("Index below {0}: {1}",
yIndexBelow, If(yIndexBelow = -1, "N/A", rows(yIndexBelow).Value))
Console.WriteLine("Index above {0}: {1}",
yIndexAbove, If(yIndexAbove = -1, "N/A", rows(yIndexAbove).Value))
End Sub
实现IComparable时的输出:
yVal:6.7
行:5
指数低于0:5
指数高于-1:N / A.
行:5,6,2,10,6,12,1
指数低于1:6
指数高于3:10
这很有趣,我检查了Google / SO / MSDN是否有任何关于此行为的提及,但找不到任何内容。从逻辑上讲,它是有道理的,但可能导致混淆点。
答案 1 :(得分:0)
答案是因为Min()
和Max()
正在尝试比较未实现Row
的{{1}}。第一行工作的原因是因为IComparable
只有一行可以返回(在我的测试用例中)。
所以这个故事的寓意是:比较可比的东西(呃!)和 Max()
和Max()
如果只有一个对象,就不会抱怨可比性在集合中。