突破了朱莉娅的一个循环

时间:2016-09-10 22:06:16

标签: for-loop julia break

我有Vector Vector个不同长度的W 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 。这些最后的向量包含0到150,000之间的整数,步长为5,但也可以为空。我试图计算每个向量的经验cdf。我可以计算这些cdf遍历每个向量和每个整数,如此

j >= maximum(v)

但是,这种方法效率低,因为maximum(v)的cdf等于1,有时j远低于150,000。

我的问题是:我如何包含一个条件,该条件会突破j > maximum(v)的{​​{1}}循环,但仍会为其余的pcdf = 1.0分配j?< / p>

我尝试在break时添加j > maximum(v),但这当然会阻止循环继续j的剩余时间。此外,我可以打破循环,然后使用get!来访问/包含1.0以后在cdfdict中找不到的密钥,但这不是我正在寻找的。

4 个答案:

答案 0 :(得分:2)

break只有一个等级。您可以通过包装for循环函数并使用return(而不是放置它的地方)或使用@goto来执行您想要的操作。

或者您要破解的地方,您可以切换布尔值breakd=true然后中断,并在较大的循环底部执行if breakd break end

答案 1 :(得分:2)

您可以使用另一个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 = maximum(v)
for j in 0:5:150_000
    if j > m
        cdfdict[i, j] = 1.0
    else
        pcdf = count(x -> x <= j, v)/len
        cdfdict[i, j] = pcdf
    end
end

答案 2 :(得分:2)

详细说明我的评论,这个答案详述了一个填充数组而不是Dict的实现。

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

W = [rand(0:mv,rand(0:10)) for mv in floor(Int,exp(log(150_000)*rand(10)))]

接下来创建一个填充1.0s的正确大小的数组:

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

此实现使用sort,有时可能会很慢,但其他实现基本上将向量与各种值进行比较,在大多数情况下这些值甚至更慢。

答案 3 :(得分:1)

另一个答案给出了使用Array的实现,该Array通过对样本进行排序并用分位数值填充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:

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)注意使用onezero来准备改变Real类型 - 这是一种很好的做法。 (b)同时添加各种@inbounds@simd应进一步优化。 (c)建议将此代码放在一个函数中(本答案中没有这样做)。 (d)如果空样本的CDF为零(这意味着没有样本在语义上意味着巨大的样本),那么第二个for可以简化。

有关更多选项,请参阅其他答案,并提醒:过早优化是所有邪恶的根源(Knuth ??)