根据差异,将数组过滤为每10个十行一行? [英] Filter array to one row per multiple of ten, based on difference?

查看:116
本文介绍了根据差异,将数组过滤为每10个十行一行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个数组,用于保存结果集中的值。我检索数组的代码大纲是:

  public String [] [] ref_Details( ){
int i = 0;
String a [] [] = new String [47] [11];
try
{
con = getConnection();
stmt = con.createStatement();
String sql =select b.LOGTIME,b.beam_current,b.beam_energy ......; //缩短
stmt.executeQuery(sql);
rs = stmt.getResultSet();

while(rs.next()){
for(int j = 0; j< 11; j ++)
a [i] [j] = rs.getString(j 1);

i ++;
}
}
catch(例外e){...}
finally {
closeConnection(stmt,rs,con);
}
返回a;
}

获得的样本表是:





从表中可以清楚地看到,第二列 beam_current 的值接近10到0的每个整数倍:(0,10,20 ...... 220) )。我想过滤我的数据集,这样,对于每个十的倍数,我只选择最接近该倍数的行。为此,我:


  1. beam_current 的所有行中减去10并找到获得的差异:差异最小的行是我对10的倍数感兴趣的唯一行.T

  2. 重复步骤1,直到从所有行中减去总计220 。

我的预期结果是22行,而不是样本数据中的原始47行。例如,上面的示例数据图片中编号为21的行将对应于值 130 的所选行。



<我的问题是我没有看到我预期的结果。我尝试的代码是:

  public int [] ref_BeamCurrent(){
int i = 0;
int [] arr = new int [47];
try
{
con = getConnection();
...
rs = stmt.getResultSet();

while(rs.next())
{
for(i = 0; i< arr.length; i ++)
{
arr [ i] = rs.getInt(2);
System.out.println(arr);
while(i< arr.length&& number< = 210)
{
arr [i] = arr [i] - number;
System.out.println(arr);
number = number + 10;
System.out.println(number);
i = i + 1;
// System.out.println(arr);
}
}
}
}
catch(例外e){...}
finally {...}
return arr ;
}

这段代码似乎完全选择了错误的行 - 我做错了什么?

解决方案

我认为你应该以不同的方式思考这个问题。你想要做的是找到每行十的倍数距离。




  • 十分之一的最接近倍数由表达式 double mult = 10d * Math.round(v / 10d)给出)

  • 距离十的倍数的距离由表达式 double delta = Math.abs(v-mult)

  • 对于 mult 的任何值,您想要的行是 delta value。



因此,您只需迭代行一次。


  1. 获取行的 beam_value 并找到 mult delta

  2. 如果行的 delta 比之前找到的 delta 更接近 mult ,然后记录 mult 的那一行,否则忽略它。

  3. 重复,直到没有更多的行。

另请注意,此方法将阻止单行记录十个以上的十个倍数,用其他方法很难防止。



通过示例(我伪造了数据,因为我没有你的SQL查询)。输入数据:

 `0.5,12.10,13.00,16.01,21.52` 

给出下面的输出,这是正确的(索引1比索引2更接近 10 ,和索引4比索引3更接近 20

 
10x行值
0 0 0.5000
10 1 12.1000
20 4 21.5200

代码:

  public static void findClosestRowsToMultiplesOfTen(){
//假行值
double [] vals = new double [] {0.5,12.10,13.00,16.01,21.52};

//获取最大值,以及它的倍数为10以获得桶数
double max = Double.MIN_VALUE;
for(double v:vals)max = Math.max(max,v);
int bucketCount = 1 +(int)(max / 10);

//初始化桶数组以存储最接近的值
double [] [] buckets = new double [bucketCount] [3];
for(int i = 0; i< bucketCount; i ++){
//在第一个元素中存储当前最小的delta
buckets [i] [0] = Double.MAX_VALUE;
//将当前最接近的索引存储在第二个元素中
buckets [i] [1] = -1d;
//将当前最接近的值存储在第三个元素中
buckets [i] [2] = Double.MAX_VALUE;
}

//迭代行
for(int i = 0; i< vals.length; i ++)
{
// get行
double v = vals [i];
//获得10的最接近倍数v
double mult = getMultipleOfTen(v);
//从10的倍数得到v的绝对距离
double delta = Math.abs(mult-v);
//根据`mult`
int bIdx =(int)(mult / 10d)的值获取bucket索引;
//测试此桶的最后已知最小增量
if(buckets [bIdx] [0]> delta)
{
//这比最后一个已知的最小三角洲
桶[bIdx] [0] = delta;
buckets [bIdx] [1] = i;
buckets [bIdx] [2] = v;
}
}

//打印出结果
System.out.format(10x行值%n);
for(int i = 0; i< buckets.length; i ++)
{
double [] bucket = buckets [i];
int multipleOfTen = i * 10;
double rowIndex = bucket [1];
double rowValue = bucket [2];
System.out.format(%,2d%,4.0f%.4f%n,
multipleOfTen,rowIndex,rowValue);
}
}
public static double getMultipleOfTen(double v)
{
return 10d * Math.round(v / 10d);
}


I have an array which holds the values from a resultset. The outline of my code to retrieve the array is:

public String[][] ref_Details() {
  int i = 0;
  String a[][] = new String[47][11];
  try
  {  
    con = getConnection();
    stmt = con.createStatement();
    String sql=" select b.LOGTIME, b.beam_current, b.beam_energy ..."; // shortened
    stmt.executeQuery(sql);
    rs = stmt.getResultSet();

    while(rs.next()) {
      for(int j=0; j<11; j++)
        a[i][j] = rs.getString(j+1);

      i++;
    }
  }
  catch( Exception e ) { ... }
  finally {
    closeConnection(stmt, rs, con);
  }
  return a;
}

The sample table obtained is:

From the table it is clear that the second column beam_current has values which are near to each integer multiple of ten from 0 to 220: (0, 10, 20 ... 220). I want to filter my data set so that, for each multiple of ten, I only select the row closest to that multiple. For this I:

  1. subtract 10 from all the rows of beam_current and find the differences obtained: the row with the smallest difference is the only row in which I'm interested for that multiple of 10. T
  2. repeat step 1 until a total of 220 is subtracted from all rows.

My expected result is 22 rows instead of the original 47 from the sample data. For example, the row numbered 21 in the sample data picture above would correspond to the selected row for the value 130.

My problem is that I'm not seeing my expected results. The code I tried is:

public int[] ref_BeamCurrent() {
  int i = 0;
  int[] arr = new int[47];
  try
  {  
    con = getConnection();
    ...
    rs = stmt.getResultSet();

    while(rs.next()) 
    { 
      for(i=0; i<arr.length; i++)
      {
        arr[i] = rs.getInt(2);
        System.out.println(arr);
        while (i < arr.length && number <= 210)
        {
          arr[i] = arr[i] - number;
          System.out.println(arr);
          number = number + 10;
          System.out.println(number);
          i = i + 1;
          // System.out.println(arr);
        }
      }
    }
  }
  catch( Exception e ) { ... }
  finally { ... }
  return arr;
}

This code seems to be selecting entirely the wrong rows - what am I doing wrong?

解决方案

I think you should think about this in a different way. What you want to do is find the distance from a multiple of ten for each row.

  • The closest multiple of ten is given by the expression double mult = 10d * Math.round(v / 10d)
  • The distance from the multiple of ten is given by the expression double delta = Math.abs(v - mult)
  • For any value of mult, the row you want is the one with the smallest delta value.

Therefore you only have to iterate the rows once.

  1. Get the beam_value for a row and find it's mult and delta.
  2. If the row's delta is closer than any previously found delta for mult, then log that row for that mult, otherwise ignore it.
  3. repeat until there are no more rows.

Also note that this approach will prevent a single row being logged against more than one multiple of ten, which is hard to prevent with other approaches.

By example (and I have faked the data as I don't have your SQL query). The input data:

`0.5, 12.10, 13.00, 16.01, 21.52`

gives the output below, which is correct (index 1 is closer to 10 than index 2, and index 4 is closer to 20 than index 3):

   10x  row value
     0    0 0.5000
    10    1 12.1000
    20    4 21.5200

with the code:

public static void findClosestRowsToMultiplesOfTen() {
    // fake row values
    double[] vals = new double[]{ 0.5, 12.10, 13.00, 16.01, 21.52 };

    //  get the max value, and its multiple of ten to get the number of buckets
    double max = Double.MIN_VALUE;
    for (double v : vals) max = Math.max(max, v);
    int bucketCount = 1 + (int)(max/10);

    //  initialise the buckets array to store the closest values
    double[][] buckets = new double[bucketCount][3];
    for (int i = 0; i < bucketCount; i++){
        // store the current smallest delta in the first element
        buckets[i][0] = Double.MAX_VALUE; 
        // store the current "closest" index in the second element
        buckets[i][1] = -1d;
        // store the current "closest" value in the third element
        buckets[i][2] = Double.MAX_VALUE;
    }

    //  iterate the rows
    for (int i = 0; i < vals.length; i++)
    {
        //  get the value from the row
        double v = vals[i];
        //  get the closest multiple of ten to v
        double mult = getMultipleOfTen(v);
        //  get the absolute distance of v from the multiple of ten
        double delta = Math.abs(mult - v);
        //  get the bucket index based on the value of `mult`
        int bIdx = (int)(mult / 10d);
        //    test the last known "smallest delta" for this bucket
        if (buckets[bIdx][0] > delta)
        {
            //  this is closer than the last known "smallest delta"
            buckets[bIdx][0] = delta;
            buckets[bIdx][1] = i;
            buckets[bIdx][2] = v;
        }
    }

    //   print out the result
    System.out.format("    10x row value%n");
    for (int i = 0; i < buckets.length; i++)
    {
        double[] bucket = buckets[i];
        int multipleOfTen = i * 10;
        double rowIndex = bucket[1];
        double rowValue = bucket[2];
        System.out.format("    %,2d %,4.0f %.4f%n", 
          multipleOfTen, rowIndex, rowValue);
    }
}
public static double getMultipleOfTen(double v)
{
    return 10d * Math.round(v / 10d);
}

这篇关于根据差异,将数组过滤为每10个十行一行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆