在Julia中随机输出的数组理解

Jos*_*ath 3 arrays random list-comprehension julia

这个问题是如果我今天刚才问的延伸.基本上,我试图在Julia中编写一个数组理解,调用一个f(x)输出为随机数的函数.当达到小于0.5的随机数时,我希望它杀死该函数.我能够编写以下代码:

X = [f(i)for i in 1:1:100 if(j = f(i); j <0.5?false:j> 0.5)]

这个问题是,它调用了两个单独的实例f(x),并且因为f(x)每次都是随机的,所以上面不会在正确的实例中杀死for循环.我试过了

X = [J = f(i)for i in 1:1:100 if(J <0.5?false:J> 0.5)]

作为尝试保存特定的随机数,但它告诉我J没有定义.有没有办法保存这个特定的随机数来执行我的数组理解?

Dan*_*etz 6

坚持一线解决方案并受@TasosPapastylianou的启发,快速解决方案将是:

X = ( r=Vector{Float64}() ; 
  any(i->(v=f(i) ; v>0.5 ? ( push!(r,v) ; false) : true), 1:100) 
  ; r )
Run Code Online (Sandbox Code Playgroud)

[单行被分成三行,因为它有点长;)]

由于f缺少,要测试此版本,请使用以下版本粘贴此版本rand:

(r=ones(0); any(i->(v=rand(); v>0.5 ? (push!(r,v); false) : true), 1:10); r)
Run Code Online (Sandbox Code Playgroud)

它的基准测试比凤阳的功能慢了约10%.聪明的一点是利用any短路实现.

ADDENDUM:这里概括一下凤阳的一个版本takewhile来抽象这个问题的答案:

collectwhilecond(f,cond,itr) = begin
    r=Vector{typeof(f(first(itr)))}()
    all(x->(y=f(x); cond(y) ? (push!(r,y);true):false),itr)
    return r
end
Run Code Online (Sandbox Code Playgroud)

现在,我们可以实现上面的答案(用jokeras f):

julia> joker(i) = 1.0 + 4*rand() - log(i)

julia> collectwhilecond(joker, x->x>=0.5, 1:100)
3-element Array{Float64,1}:
 4.14222
 3.42955
 2.76387
Run Code Online (Sandbox Code Playgroud)

collectwhilecond如果Julia推断出f返回类型,那么它也是类型稳定的.

编辑:使用@ tim的推荐方法推断返回类型f而不拉动元素,itr并且不会产生不稳定的f生成错误,新的collectwhilecond是:

collectwhilecond(f,cond,itr) = begin
    t = Base.promote_op(f,eltype(itr))  # unofficial and subject to change
    r = Vector{t}()
    all( x -> ( y=f(x) ; cond(y) ? (push!(r,y) ; true) : false), itr )
    return r
end
Run Code Online (Sandbox Code Playgroud)


Tas*_*nou 5

你要做的事实上是一个简单的filter操作:

filter(x -> x >= 0.5, [f(i) for i in 1:10])
Run Code Online (Sandbox Code Playgroud)

这基本上是我们if在v0.5之前在julia中的列表推导中实现该部件之前首先依赖的东西


编辑:正如丹指出的那样,你可能在保留所有元素之后直到第一个<0.5的元素,例如:

L = [f(i) for i in 1:10]; L[1 : findfirst(L.<0.5) - 1]
Run Code Online (Sandbox Code Playgroud)

但是,在这种情况下,正如其他人所指出的那样,你也可以选择正常的for循环.列表推导将始终首先处理整个列表,因此它不会更快.你可以使用一个生成器,但是你必须创建自己的特殊机制才能使它停在正确的状态(正如凤阳建议的那样takewhile).

因此,为了回答评论中的问题,在这种情况下你能做的最快的事情是正常的for循环,它会适当地破坏.此外,它最好包含在函数中而不是全局计算,如果指定变量的类型,它将进一步加速.