【问题标题】:Custom searchsortedfirst method自定义 searchsortedfirst 方法
【发布时间】:2018-01-05 06:48:34
【问题描述】:

我是 Julia lang 的新手,所以我仍在努力阅读 Julia 文档。这是其中的一部分,我正在寻找特别是 bolded 部分的解释。

Base.Sort.searchsortedfirst — 函数。

searchsortedfirst(a, x, [by=,] [lt=,] [rev=false])

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

Website

我的数组如下所示:

A = Vector{Record}()

在哪里

type Record
     y::Int64
     value::Float64
end

现在这是我的问题。我想在我的数组上调用上述方法并获取记录,其中给定 x 等于 y 在此记录(Record.y == x)。猜猜我必须写“by”转换或“lt”比较器?还是两者都有?

任何帮助都会得到帮助:)

【问题讨论】:

  • 听起来像find(r->r.y == x, A)
  • @crstnbr 得到了排序数组,所以如果函数小于 O(n) 会很酷。谢谢你的提议:)

标签: arrays sorting vector julia


【解决方案1】:

@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) 运营商&lt;&lt;===&gt;=&gt;,实际上都只是在后台调用islessisequal,所以所有这些运算符现在都可以与您的新类型一起使用,例如MyType(1.0) &gt; MyType(2.0) 返回@ 987654346@.

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

【讨论】:

  • 哦,这很有帮助!所以基本上你在做什么是你在这个'Base'类中重载一个方法,我猜?您能详细介绍一下它的用法吗?或链接一些网站?感谢您为澄清所做的努力!
  • @J.Kennsy 我已经对我的答案进行了重大修改,以包含一些新信息,并希望能回答您的问题。让我知道是否还有其他需要澄清的地方。
【解决方案2】:

您可以定义一个自定义的小于运算并通过lt 关键字参数将其提供给searchsortedfirst

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)-&gt;r.y&lt;x 是一个 anonymous function 定义您的自定义小于。它需要两个参数(要比较的元素)。第一个是来自A 的元素,第二个是要比较的固定元素。

【讨论】:

  • 这正是我想要的。谢谢你的解释:)
  • 不错的答案。我打算在这里添加一条评论,您也可以扩展 Base.islessBase.isequal 但它最终有点长,所以我把它写成第二个答案。但我认为这两种方法都很“儒雅”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-03
  • 2011-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
相关资源
最近更新 更多