如何在Ruby中找到两个线性变换数组的对应元素?

时间:2014-07-29 00:46:20

标签: ruby arrays transformation linear minimum

我有两个具有唯一元素的浮点数(x,y),其中一个是另一个y=a*x+b的线性变换,例如:

a=0.95;
b1=3.33;
b2=5.55;
x=[1,3,4,6,9,13,20,22,31,35,37,40];
y=t1.collect.with_index{|z,i| i>6 ? z*a+b1 : z*a+b2}
=> [6.5, 8.4, 9.35, 11.25, 14.1, 17.9, 24.55, 24.23, 32.78, 36.58, 38.48, 41.33]

线性变换将两个不同的b值应用于x数组。我们假设我不知道b值的规则,这里是索引i的函数。

我的目标是,如果我知道a的价值,并且我也知道b以双元素数组bs=[b1,b2]形式的可能值,那么我想找出b的每个元素的对应y值,即使两个数组(x,y)被加扰。我的想法(没有正常工作,我需要帮助):

def ybs(x,y,bs,a)
  difference=0.0
  xelem=0.0
  return y.map do |z| 
    cb=bs.min_by do |b| 
      xelem=x.min_by do |q| 
        (q-(z-b)*1/a).abs
      end
      difference=(xelem-(z-b)*1/a).abs
    end
    difference=(xelem-(z-cb)*1/a).abs
    [z,xelem,(z-cb)*1/a,cb,difference]
   end
end

它将为y数组的每个元素返回4个值:

[<value from y>,<correspondent value from x>,<inverse transformed value of y, should be equal to xelem>,<correspondent b value of the linear transformation>,<difference, error, usually 0.0>]

我拨打ybs(x,y,bs,a)时的输出:

[[1, 6.5, -2.4526315789473685, 3.33, 8.952631578947368],
 [3, 6.5, -0.34736842105263166, 3.33, 6.847368421052631],
 [4, 6.5, 0.7052631578947368, 3.33, 5.794736842105263],
 [6, 6.5, 2.8105263157894735, 3.33, 3.6894736842105265],
 [9, 6.5, 5.968421052631579, 3.33, 0.5315789473684207],
 [13, 8.4, 7.842105263157896, 5.55, 0.5578947368421048],
 [20, 14.1, 17.547368421052635, 3.33, 3.4473684210526354],
 [22, 17.9, 17.31578947368421, 5.55, 0.5842105263157897],
 [31, 24.55, 26.789473684210527, 5.55, 2.2394736842105267],
 [35, 32.78, 33.33684210526316, 3.33, 0.5568421052631578],
 [37, 32.78, 33.10526315789474, 5.55, 0.3252631578947387],
 [40, 36.58, 38.6, 3.33, 2.020000000000003]]

我需要这种方法用于我的字幕同步程序,其中字幕的不同部分是&#39;时间码可以移动不同的数量,例如当电影的不同版本中缺少场景时。

1 个答案:

答案 0 :(得分:1)

问题在于你没有将订购的对保持在一起。对于每个y值,您的代码都会认为&#39;与之关联的x是(q-(z-b)*1/a).abs最少的x。然而,可能是因为错误而且#34; b正在考虑的y值的值,以及错误的x值将导致(q-(z-b)*1/a).abs的值略微(或大大)小于您通过&#34;右&#34;得到的值。 bx值。

我运行了你的代码(为了清晰起见,将数值四舍五入)得到了:

[6.5, 1.0, 1.0, 5.55, 0.0]
[8.4, 3.0, 3.0, 5.55, 0.0]
[9.35, 4.0, 4.0, 5.55, 0.0]
[11.25, 6.0, 6.0, 5.55, 0.0]
[14.1, 9.0, 9.0, 5.55, 0.0]
[17.9, 13.0, 13.0, 5.55, 0.0]
[24.55, 20.0, 20.0, 5.55, 0.0]
[24.23, 20.0, 22.0, 3.33, 2.0]
[32.78, 31.0, 31.0, 3.33, 0.0]
[36.58, 31.0, 35.0, 3.33, 4.0]
[38.48, 35.0, 37.0, 3.33, 2.0]
[41.33, 37.0, 40.0, 3.33, 3.0]

您可以看到x值不遵循原始序列。由于没有必要抓住机会让他们与错误的&#x; s相关联,所以让我们强迫他们保持联系。

以下是我修改代码的方式,以便将yx放在一起。

def ybs(pairs,bs,a)
  difference=0.0
  xelem=0.0
  return pairs.map do |pair|
    x,y = pair[0], pair[1]
    cb = bs.min_by do |b|
      (x-(y-b)*1/a).abs
    end
    difference = (x-(y-cb)*1/a).abs
    [y,x,(y-cb)*1/a,cb,difference]
  end
end

a=0.95;
b1=3.33;
b2=5.55;
bs = [b1, b2]
x=[1,3,4,6,9,13,20,22,31,35,37,40];
y=x.collect.with_index{|z,i| i>6 ? z*a+b1 : z*a+b2}
c = x.count-1
pairs = (0..c).collect do |i|
  [x[i],y[i]]
end

r = ybs(pairs,bs,a)
r.each do |q|
  (0..4).each do |p|
    q[p] = q[p].round(2)
  end
  p q
end

这是我的输出:

[6.5, 1.0, 1.0, 5.55, 0.0]
[8.4, 3.0, 3.0, 5.55, 0.0]
[9.35, 4.0, 4.0, 5.55, 0.0]
[11.25, 6.0, 6.0, 5.55, 0.0]
[14.1, 9.0, 9.0, 5.55, 0.0]
[17.9, 13.0, 13.0, 5.55, 0.0]
[24.55, 20.0, 20.0, 5.55, 0.0]
[24.23, 22.0, 22.0, 3.33, 0.0]
[32.78, 31.0, 31.0, 3.33, 0.0]
[36.58, 35.0, 35.0, 3.33, 0.0]
[38.48, 37.0, 37.0, 3.33, 0.0]
[41.33, 40.0, 40.0, 3.33, 0.0]

所有错误都很小,而且b是正确的......它们是5.55直到第7行,在那里它们会切换到3.33,正如您的规则所规定的那样。