自定义searchsortedfirst方法

时间:2018-01-03 13:59:04

标签: arrays sorting vector julia

我是Julia lang的新人,所以我仍然在努力阅读Julia文档。这是它的一部分,我正在寻找具体的解释粗体部分。

  

Base.Sort.searchsortedfirst - 功能。

     

searchsortedfirst(a,x,[by =,] [lt =,]   [转=假])

     

返回大于或等于x的第一个值的索引,   按照指定的顺序。如果x更大,则返回长度(a)+1   比一个中的所有值。假设a被排序。

Website

我的数组看起来像这样:

A = Vector{Record}()

其中

type Record
     y::Int64
     value::Float64
end

现在这是我的问题。我想在我的数组上调用上面提到的方法,并获得Record在此Record(Record.y == x)中给定x等于y的位置。我猜我必须写'by'transfrom或'lt'比较器?或两者兼而有之?

任何帮助都会被评估:)

2 个答案:

答案 0 :(得分:4)

@crstnbr为searchsortedfirst的一次性使用案例提供了一个非常好的答案。我认为值得补充的是,还有一个更永久的解决方案。如果您的类型Record表现出自然顺序,那么只需将Base.islessBase.isequal扩展为新类型即可。以下示例代码显示了这可能适用于您可能定义的某些新类型:

struct MyType ; x::Float64 ; end  #Define some type of my own
yvec = MyType.(sort!(randn(10)))  #Build a random vector of my type
yval = MyType(0.0)                #Build a value of my type
searchsortedfirst(yvec, yval)     #ERROR: this use of searchsortedfirst will throw a MethodError since julia doesn't know how to order MyType
Base.isless(y1::MyType, y2::MyType)::Bool = y1.x < y2.x   #Extend (aka overload) isless so it is defined for the new type
Base.isequal(y1::MyType, y2::MyType)::Bool = y1.x == y2.x #Ditto for isequal
searchsortedfirst(yvec, yval)     #Now this line works

值得注意的一些要点:

1)在我重载islessisequal的步骤中,我在方法定义前加上Base.。这是因为islessisequal函数最初在Base中定义,其中Base指的是每次启动julia时自动加载的核心julia包。通过使用Base.作为前缀,我确保将我的新方法添加到这两个函数的当前方法集中,而不是替换它们。请注意,我也可以通过省略Base.但事先包含import Base: isless, isequal的行来实现此目的。就个人而言,我更喜欢我上面这样做的方式(对于过度迂腐,你也可以两者兼顾)。

2)我可以定义islessisequal但我想要。这是我的类型和我的方法扩展。因此,您可以选择您认为新类型的自然顺序。

3)运营商<<===>=>,实际上只需在引擎盖下调用islessisequal,所以所有这些运营商现在都会使用新类型,例如MyType(1.0) > MyType(2.0)返回false

4)任何使用上述比较运算符的julia函数现在都可以使用您的新类型,只要该函数是参数化定义的(几乎Base中的所有内容都是)。

答案 1 :(得分:3)

您可以定义自定义小于操作,并通过searchsortedfirst关键字参数将其提供给lt

julia> type Record
            y::Int64
            value::Float64
       end

julia> A = Vector{Record}()
0-element Array{Record,1}

julia> push!(A, Record(3,3.0))
1-element Array{Record,1}:
 Record(3, 3.0)

julia> push!(A, Record(4,3.0))
2-element Array{Record,1}:
 Record(3, 3.0)
 Record(4, 3.0)

julia> push!(A, Record(5,3.0))
3-element Array{Record,1}:
 Record(3, 3.0)
 Record(4, 3.0)
 Record(5, 3.0)

julia> searchsortedfirst(A, 4, lt=(r,x)->r.y<x)
2

此处,(r,x)->r.y<x是一个anonymous function,定义您的自定义小于。它需要两个参数(要比较的元素)。第一个是来自A的元素,第二个是要与之比较的固定元素。