2017-05-21 29 views
3

环路I具有的代码在朱以下行:杀死对于朱莉娅阵列理解

X=[(i,i^2) for i in 1:100 if i^2%5==0] 

基本上,它从i=1 to 100返回元组(i,i^2)的列表,如果的i^25余数是零。我想要做的是,在阵列理解中,如果i^2变得大于1000,则跳出for循环。但是,如果我实现

X=[(i,i^2) for i in 1:100 if i^2%5==0 else break end] 

我得到的错误:syntax: expected "]"

有没有什么办法轻松摆脱这个数组中的循环?我试着在网上寻找,但没有出现。

回答

5

我不这么认为。你总是可以只

tmp(i) = (j = i^2; j > 1000 ? false : j%5==0) 
X=[(i,i^2) for i in 1:100 if tmp(i)] 
+0

在后面的问题http://stackoverflow.com/questions/44101965/array-comprehension-with-a-random-output-in-julia(编辑:和更近的答案在这里)有评论说它最好只写出循环。我同意这一点 - 这只是试图回答提出的问题。 –

5

它是环“假”,所以你不能break它。看一看下面的降低代码:

julia> foo() = [(i,i^2) for i in 1:100 if i^2%5==0] 
foo (generic function with 1 method) 

julia> @code_lowered foo() 
LambdaInfo template for foo() at REPL[0]:1 
:(begin 
     nothing 
     #1 = $(Expr(:new, :(Main.##1#3))) 
     SSAValue(0) = #1 
     #2 = $(Expr(:new, :(Main.##2#4))) 
     SSAValue(1) = #2 
     SSAValue(2) = (Main.colon)(1,100) 
     SSAValue(3) = (Base.Filter)(SSAValue(1),SSAValue(2)) 
     SSAValue(4) = (Base.Generator)(SSAValue(0),SSAValue(3)) 
     return (Base.collect)(SSAValue(4)) 
    end) 

输出显示array comprehension经由Base.Generator这需要一个迭代作为输入来实现。目前它只支持[if cond(x)::Bool]“警卫”,所以在这里没有办法使用break

针对您的特殊情况下,一个解决方法是使用isqrt

julia> X=[(i,i^2) for i in 1:isqrt(1000) if i^2%5==0] 
6-element Array{Tuple{Int64,Int64},1}: 
(5,25) 
(10,100) 
(15,225) 
(20,400) 
(25,625) 
(30,900) 
3

使用for环路朱莉娅被认为是地道的,可能是在这种情况下更具有可读性。另外,它可能会更快。

具体做法是:

julia> using BenchmarkTools 

julia> tmp(i) = (j = i^2; j > 1000 ? false : j%5==0) 
julia> X1 = [(i,i^2) for i in 1:100 if tmp(i)]; 

julia> @btime [(i,i^2) for i in 1:100 if tmp(i)]; 
    471.883 ns (7 allocations: 528 bytes) 

julia> X2 = [(i,i^2) for i in 1:isqrt(1000) if i^2%5==0]; 

julia> @btime [(i,i^2) for i in 1:isqrt(1000) if i^2%5==0]; 
    281.435 ns (7 allocations: 528 bytes) 

julia> function goodsquares() 
      res = Vector{Tuple{Int,Int}}() 
      for i=1:100 
       if i^2%5==0 && i^2<=1000 
        push!(res,(i,i^2)) 
       elseif i^2>1000 
        break 
       end 
      end 
      return res 
     end 
julia> X3 = goodsquares(); 

julia> @btime goodsquares(); 
    129.123 ns (3 allocations: 304 bytes) 

因此,另一种提高一倍是没有无视和长函数提供足够的空间,用于照明的意见。

+1

除了提前终止之外,编写循环的内容不应该有任何内在的更快 - 这就是理解代码归结为的内容。有可能允许中断或继续理解,但语义有点不清楚。是否有其他语言(例如Python)允许它? – StefanKarpinski

+0

@StefanKarpinski“isqrt”版本的终止速度与循环版本一样快,但速度仍然慢了2倍。这是为什么? (猜测:采取根慢) –

+0

回复:最后的评论,'isqrt'不是罪魁祸首。对上限进行手工编码并在更多条目上运行(高达10,000)仍然有一个2x因子支持'goodsquares' –