For loop 在朱莉娅身上打破循环

For loop 在朱莉娅身上打破循环,for-loop,julia,break,For Loop,Julia,Break,我有一个向量的向量s,长度不同W。最后的这些向量包含0到150000之间的整数(以5为单位),但也可以为空。我试图计算每个向量的经验cdf。我可以像这样迭代每个向量和每个整数来计算这些cdf cdfdict = Dict{Tuple{Int,Int},Float64}() for i in 1:length(W) v = W[i] len = length(v) if len == 0 pcdf = 1.0 else for j i

我有一个
向量
向量
s,长度不同
W
。最后的这些向量包含0到150000之间的整数(以5为单位),但也可以为空。我试图计算每个向量的经验cdf。我可以像这样迭代每个向量和每个整数来计算这些cdf

cdfdict = Dict{Tuple{Int,Int},Float64}()
for i in 1:length(W)
    v = W[i]
    len = length(v)
    if len == 0
        pcdf = 1.0
    else
        for j in 0:5:150_000
            pcdf = length(v[v .<= j])/len
            cdfdict[i, j] = pcdf
        end
    end
end
cdfdict=Dict{Tuple{Int,Int},Float64}()
对于1中的i:长度(W)
v=W[i]
len=长度(v)
如果len==0
pcdf=1.0
其他的
对于0:5:150_000中的j
pcdf=长度(v[v.=最大值(v)
,有时该
最大值(v)
将远低于150000

我的问题是:我如何能够包括一个条件,即对于
j>最大值(v)
,打破
j
循环,但对于
j
的其余部分,仍然分配
pcdf=1.0


我尝试在
j>最大值(v)时包含
中断
但这当然会阻止循环在
j
s的其余部分继续。此外,我可以中断循环,然后使用
get!
访问/包括
1.0
,以便稍后在
cdfdict
中找不到的密钥,但这不是我要找的。

break
只执行一个级别。您可以做您想做的事情y包装for循环函数并使用
return
(而不是放break的位置),或使用
@goto


或者在要中断的位置,可以切换布尔值
breakd=true
,然后中断,在较大循环的底部,如果breakd break end,则可以使用另一个
for
循环将所有剩余元素设置为1.0。内部循环变为

m = maximum(v)
for j in 0:5:150_000
    if j > m
        for k in j:5:150_000
            cdfdict[i, k] = 1.0
        end
        break
    end
    pcdf = count(x -> x <= j, v)/len
    cdfdict[i, j] = pcdf
end
m=最大值(v)
对于0:5:150_000中的j
如果j>m
对于k in j:5:150000
cdfdict[i,k]=1.0
结束
打破
结束
pcdf=计数(x->x m
cdfdict[i,j]=1.0
其他的

pcdf=count(x->x为了详细说明我的评论,这个答案详细说明了一个填充数组而不是Dict的实现

首先创建一个随机测试用例:

W = [rand(0:mv,rand(0:10)) for mv in floor(Int,exp(log(150_000)*rand(10)))]
接下来,创建一个大小合适的数组,数组中填充1.0:

cdfmat = ones(Float64,length(W),length(0:5:150_000));
现在填写CDF的开头:

for i=1:length(W)
    v = sort(W[i])
    k = 1
    thresh = 0
    for j=1:length(v)
        if (j>1 && v[j]==v[j-1])
            continue
        end
        pcdf = (j-1)/length(v)
        while thresh<v[j]
            cdfmat[i,k]=pcdf
            k += 1
            thresh += 5
        end
    end
end
cdfmat = zeros(Float64,n,hl);  # empty histograms
for i=1:n                      # drop samples into histogram bins
  for j=1:length(W[i])
    cdfmat[i,1+(W[i][j]+w-1)÷5]+=one(Float64)
  end
end
cumsum!(cdfmat,cdfmat,2)       # calculate pre-CDF by cumsum
for i=1:n                      # normalize each CDF by total 
  if cdfmat[i,hl]==zero(Float64) # check if histogram empty?
    for j=1:hl                 # CDF of 1.0 as default (might be changed)
      cdfmat[i,j] = one(Float64)
    end
  else                         # the normalization factor calc-ed once
    f = one(Float64)/cdfmat[i,hl]
    for j=1:hl
      cdfmat[i,j] *= f
    end
  end
end
i=1时的
:长度(W)
v=排序(W[i])
k=1
thresh=0
对于j=1:长度(v)
如果(j>1&&v[j]==v[j-1])
持续
结束
pcdf=(j-1)/长度(v)

thresh另一个答案给出了一个使用数组的实现,该数组通过对样本进行排序并用分位数值填充CDF箱来计算CDF。由于整个数组都是这样填充的,因此在数组上进行另一次传递不应该花费过多的成本(我们已经容忍了单次传递)。通过计算数组中的直方图并使用
cumsum
生成CDF,可以避免排序位及其伴随的分配。也许代码可以更好地解释这一点:

初始化大小、长度和宽度:

n = 10; w = 5; rmax = 150_000; hl = length(0:w:rmax)
制作一个示例:

W = [rand(0:mv,rand(0:10)) for mv in floor(Int,exp(log(rmax)*rand(n)))];
计算CDF:

for i=1:length(W)
    v = sort(W[i])
    k = 1
    thresh = 0
    for j=1:length(v)
        if (j>1 && v[j]==v[j-1])
            continue
        end
        pcdf = (j-1)/length(v)
        while thresh<v[j]
            cdfmat[i,k]=pcdf
            k += 1
            thresh += 5
        end
    end
end
cdfmat = zeros(Float64,n,hl);  # empty histograms
for i=1:n                      # drop samples into histogram bins
  for j=1:length(W[i])
    cdfmat[i,1+(W[i][j]+w-1)÷5]+=one(Float64)
  end
end
cumsum!(cdfmat,cdfmat,2)       # calculate pre-CDF by cumsum
for i=1:n                      # normalize each CDF by total 
  if cdfmat[i,hl]==zero(Float64) # check if histogram empty?
    for j=1:hl                 # CDF of 1.0 as default (might be changed)
      cdfmat[i,j] = one(Float64)
    end
  else                         # the normalization factor calc-ed once
    f = one(Float64)/cdfmat[i,hl]
    for j=1:hl
      cdfmat[i,j] *= f
    end
  end
end
(a) 注意使用
one
zero
为实际类型的更改做准备-这是一个很好的实践。(b)同时添加各种
@inbounds
@simd
应该进一步优化。(c)建议将此代码放入函数中(此答案中没有这样做)。(d)如果空样本的CDF为零是可以的(这意味着没有样本在语义上意味着巨大的样本),那么可以简化
的第二个


更多选项请参见其他答案,并提醒:过早优化是万恶之源(Knuth??)

您可以使用
1
作为默认值初始化您的cdfdict,这样即使您打破它也无所谓。这几乎与在循环后使用
get!
相同……我认为@TasoPapstylenou的解决方案是最好的。但是,您可能低估了Julia中循环的速度。通过5s和filli从0循环到150000使用预设值1.0输入将花费很少的时间。@实际上不是,您只需要对“行”进行初始化在
j
for循环之前。同样,您的
pcdf=1.0
没有做任何事情……您可能打算在那里做其他事情。如果意图是使用大小
(长度(W),长度(0:5:150\u 000))的矩阵(即数组{Float64,2})在
0:5:150\u 000
中分配所有
j
会是一个更好的主意。最初将这样一个矩阵填充到
1.0
s很容易,当
最大值(v)时,应该注意CDF的尾部
很小。
@goto
if break
清晰得多,应该优先考虑。这个答案有点偏离问题,没有详细解释,所以如果需要,我会根据需要和注释中的问题进行详细编辑。
v
包含重复值的情况如何?因为一个数组被标记为答案,我将给出另一个带有数组的实现,在某些情况下可能会更好-见下文。