Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays Julia中随机输出的数组理解_Arrays_Random_Julia_List Comprehension - Fatal编程技术网

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

Arrays Julia中随机输出的数组理解,arrays,random,julia,list-comprehension,Arrays,Random,Julia,List Comprehension,。基本上,我试图在Julia中编写一个数组理解,它调用一个输出为随机数的函数f(x)。当达到小于0.5的随机数时,我希望它终止函数。我能够编写以下代码: X=[f(i)表示1:1:100中的i,如果(j=f(i);j0.5)] 这样做的问题是,它调用了f(x)的两个独立实例,并且由于f(x)每次都是随机的,因此上述操作不会在正确的实例中终止for循环。我试过了 X=[J=f(i)表示1:1:100中的i,如果(J0.5)] 试图保存那个特定的随机数,但它告诉我J没有定义。有没有办法保存这个特定的

。基本上,我试图在Julia中编写一个数组理解,它调用一个输出为随机数的函数
f(x)
。当达到小于0.5的随机数时,我希望它终止函数。我能够编写以下代码:

X=[f(i)表示1:1:100中的i,如果(j=f(i);j<0.5?错误:j>0.5)]

这样做的问题是,它调用了
f(x)
的两个独立实例,并且由于
f(x)
每次都是随机的,因此上述操作不会在正确的实例中终止for循环。我试过了

X=[J=f(i)表示1:1:100中的i,如果(J<0.5?false:J>0.5)]

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

您可以使用生成器上通常称为
takewhile
的方法来执行此操作

X = collect(takewhile(x -> x ≥ 0.5, Generator(f, 1:100)))
这需要实现
takewhile
,例如中的或您自己的(这并不难做到)
takewhile
有一个相当容易阅读的名称,并且尽可能简洁

但是,我认为编写循环通常更具可读性,也更方便:

X=Float64[]
对于i=1:100
j=f(i)
如果j<0.5
打破
其他的
推(X,j)
结束
结束

正如建议的那样,使用循环是正确的方法。但是,如果尝试“其他”解决方案,以下是简短、混乱且具有教育意义的关于堆栈溢出中很少提及的通道的内容:

collect(Channel(c->begin
        i=1
        while true 
            v = rand()
            if v<0.5 || i>100 return else put!(c,v) end
            i+=1 
        end 
    end, ctype=Float64))
collect(通道c->begin
i=1
虽然是真的
v=兰德()
如果v100返回,否则放置!(c,v)结束
i+=1
结束
结束,ctype=64)
rand()
替换为
f(i)
,视情况而定。
顺便说一句,不要使用这个解决方案,因为它比一个简单的循环慢1000倍。如果通道是一个远程通道,
f(i)
是一个大型随机模拟,那么它可能很有价值。

您试图做的基本上是一个简单的
过滤操作:

filter(x -> x >= 0.5, [f(i) for i in 1:10])
这基本上是我们在
之前首先依赖的,如果
部分是在julia v0.5之前的列表理解中实现的



编辑:正如丹指出的,您可能会在保留所有元素后,直到第一个元素坚持一行解决方案,并受到@TASOSPAPSTYLEANOU的启发,快速解决方案是:

X = ( r=Vector{Float64}() ; 
  any(i->(v=f(i) ; v>0.5 ? ( push!(r,v) ; false) : true), 1:100) 
  ; r )
[一行被拆分为三行,因为它有点长;)]

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

(r=ones(0); any(i->(v=rand(); v>0.5 ? (push!(r,v); false) : true), 1:10); r)
它比凤阳的功能慢10%。聪明的一点是利用
任何
的短路实现

附录:这里概括一下凤阳的
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
现在,我们可以将上面的答案实现为(使用
joker
as
f
):

如果Julia推断出f
的返回类型,则collectwhilecond
的类型也是稳定的

编辑:使用@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

如果您想获得最大可能的性能,我想说有两种选择,这取决于哪个是瓶颈

  • f
    速度非常快,但分配是一个问题。以下代码计算
    f
    两次,但保存在分配部分(因为
    push!
    有时会重新分配内存,请参阅):
  • i=findfirst(t->f(t)>0.5,1:100)
    w=f.(1:(i-1))
    

  • f
    非常慢,计算两次太贵。然后用
    push做一个循环已推荐。您可能想看看
    sizehint以进一步提高性能

  • 一般来说,您不需要问什么慢,什么快:ypu可以简单地用优秀的软件包对您的特定用例进行基准测试。

    为什么不编写一个循环呢?这是一个非常简单的循环。这实际上是对数组理解的滥用。写一个循环。如何确定数组的元素类型?应该使用
    Base.promote\u op(f,Int)
    ?在生成器上使用takewhile会比使用循环更快吗?我正在处理的数组包含超过一百万个元素,我希望代码运行得尽可能快。不,当然for循环总是最快的,尽管
    takewhile
    的良好实现可能会有较低的开销。@tim一个更好的方法是
    Base.\u返回类型(f,Tuple{Int})
    ,但这需要v0.6,这是一个修改过的过滤器,因为它在第一个元素丢失后停止添加元素。过滤器会比常规循环快吗?我正在尝试编写代码,以使其尽可能快地运行,并且我正在处理非常大的数组(大约几百万个元素)。@DanGetz啊,谢谢。如果没有相关的问题,细节一点也不明显。(假设链接的问题前提仍然适用)。如果
    f
    是随机的(如建议的),重新计算可能会有问题。我不认为运行
    n
    次的任何不完全平凡的函数都会比内存分配快。如果您担心内存分配,请执行
    sizehint按钮之前执行code>
    s更好。这也是我的想法,但后来我进行了基准测试,为了简单起见
    f
    (我使用了平方浮动),第一个解决方案的速度是原来的两倍(即使第二个解决方案使用了
    sizehint!
    )。这可能不仅仅是分配(我在这里找到了一些讨论,比较了
    push!
    和填充预分配数组,以防您好奇:)。不过,我还是同意推似乎是目前为止最新的nat
    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
    
    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
    
    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