简体   繁体   English

如何在java中将数组缩小到指定长度以保持元素均匀分布?

[英]How to Shrink array to specified length in java keeping elements uniformaly distributed?

I have source array, and I want to generate new array from the source array by removing a specified number of elements from the source array, I want the elements in the new array to cover as much as possible elements from the source array (the new elements are uniformly distributed over the source array) and keeping the first and last elements the same (if any). 我有源数组,我想通过从源数组中删除指定数量的元素来从源数组中生成新数组,我希望新数组中的元素覆盖源数组中尽可能多的元素(新元素均匀分布在源数组上),并保持第一个和最后一个元素相同(如果有)。

I tried this : 我尝试了这个:

public static void printArr(float[] arr)
    {
        for (int i = 0; i < arr.length; i++)
            System.out.println("arr[" + i + "]=" + arr[i]);

    }
public static float[] removeElements(float[] inputArr , int numberOfElementToDelete)
    {
       float [] new_arr = new float[inputArr.length - numberOfElementToDelete];
        int f = (inputArr.length  ) / numberOfElementToDelete;
        System.out.println("f=" + f);
        if(f == 1)
        {
            f = 2;
            System.out.println("f=" + f);
        }

       int j = 1 ;
        for (int i = 1; i < inputArr.length ; i++)
        {
            if( (i + 1) % f != 0)
            {

                System.out.println("i=" + i + "   j= " + j);
                if(j < new_arr.length)
                {
                    new_arr[j] = inputArr[i];
                    j++;
                }

            }

        }

        new_arr[0] = inputArr[0];
        new_arr[new_arr.length - 1] = inputArr[inputArr.length - 1];
        return new_arr;
    }
public static void main(String[] args)
    {

        float [] a = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
        a = removeElements(a, 6);
        printArr(a);
    }

I have made a test for(removeElements(a, 5) and removeElements(a, 4) and removeElements(a, 3)) but removeElements(a, 6); 我已经测试过(removeElements(a,5)和removeElements(a,4)和removeElements(a,3))但removeElements(a,6); gave : 给了:

 arr[0]=1.0
arr[1]=3.0
arr[2]=5.0
arr[3]=7.0
arr[4]=9.0
arr[5]=11.0
arr[6]=13.0
arr[7]=15.0
arr[8]=0.0
arr[9]=16.0

the problem is (arr[8]=0.0) it must take a value .. How to solve this? 问题是(arr [8] = 0.0)它必须取一个值..如何解决这个问题? is there any code that can remove a specified number of elements (and keep the elements distributed over the source array without generating zero in some elements)? 是否有任何代码可以删除指定数量的元素(并使元素分布在源数组中,而在某些元素中不生成零)?

EDIT : 编辑:

examples : removeElements(a, 1) ==> remove one element from the middle (7) {1,2,3,4,5,6,7,9,10,11,12,13,14,15,16} 示例:removeElements(a,1)==>从中间(7){1,2,3,4,5,6,7,9,10,11,12,13,14,15,16中删除一个元素}

removeElements(a, 2) ==> remove two elements at indexes (4,19) or (5,10) or (4,10) (no problem) removeElements(a,2)==>删除索引(4,19)或(5,10)或(4,10)的两个元素(没问题)

removeElements(a, 3) ==> remove three elements at indexes (4,9,14) or (4,10, 15) or(no problem also) removeElements(a,3)==>删除索引(4,9,14)或(4,10,15)或(也没有问题)的三个元素

removeElements(a, 4) ==> remove four elements at indexes (3,7,11 , 15) or ( 3 ,7,11,14) for example .. what I want is if I draw the values in the source array on (chart on Excel for example) and I draw the values from the new array , I must get the same line (or close to it). removeElements(a,4)==>例如,删除索引(3,7,11,15)或(3,7,11,14)的四个元素..我想要的是如果我在源数组中绘制值上(例如,在Excel上的图表),然后从新数组中绘制值,我必须获得同一行(或接近它)。

I think the main problem in your code is that you are binding the selection to 我认为代码中的主要问题是您将选择绑定到

(inputArr.length  ) / numberOfElementToDelete

This way you are not considering the first and the last elements that you don't want to remove. 这样,您就不会考虑不想删除的第一个和最后一个元素。

An example: if you have an array of 16 elements and you want to delete 6 elements it means that the final array will have 10 elements but, since the first and the last are fixed, you'll have to select 8 elements out of the remaining 14. This means you'll have to select 8/14 (0,57) elements from the array (not considering the first and the last). 例如:如果您有一个由16个元素组成的数组,并且要删除6个元素,则意味着最终的数组将包含10个元素,但是由于第一个和最后一个是固定的,因此您必须从中选择8个元素剩下的14。这意味着您必须从数组中选择8/14(0,57)个元素(不考虑第一个和最后一个)。 This means that you can initialize a counter to zero, scan the array starting from the second and sum the value of the fraction to the counter, when the value of the counter reach a new integer number (ex. at the third element the counter will reach 1,14) you'll have an element to pick and put to the new array. 这意味着您可以将计数器初始化为零,从第二个数组开始扫描数组,并将分数的值求和到计数器,当计数器的值达到新的整数(例如,在第三个元素处,计数器将达到1,14),您将有一个要拾取并放入新数组的元素。

So, you can do something like this (pseudocode): 因此,您可以执行以下操作(伪代码):

    int newLength = originalLength - toDelete;
    int toChoose = newLength - 2;
    double fraction = toChoose / (originalLength -2)
    double counter = 0;
    int threshold = 1;
    int newArrayIndex = 1;
    for(int i = 1; i < originalLength-1; i++){
        **counter += fraction;**            
        if(integerValueOf(counter) == threshold){
            newArray[newArrayIndex] = originalArray[i];
            threshold++;
            **newArrayIndex++;**
        }

     }
     newArray[0] = originalArray[0];
     newArray[newArray.length-1] = originalArray[originalArray.length-1];

You should check for the particular cases like originalArray of length 1 or removal of all the elements but I think it should work. 您应该检查特殊情况,例如长度为1的originalArray或删除所有元素,但是我认为它应该可以工作。

EDIT Here is a Java implementation (written on the fly so I didn't check for nulls etc.) 编辑这是一个Java实现(即时编写,因此我没有检查null等)。

public class Test {

    public static void main(String[] args){
        int[] testArray = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
        int[] newArray = remove(testArray, 6);
        for(int i = 0; i < newArray.length; i++){
            System.out.print(newArray[i]+" ");
        }
    }

    public static int[] remove(int[] originalArray, int toDelete){  
        if(toDelete == originalArray.length){
            //avoid the removal of all the elements, save at least first and last
            toDelete = originalArray.length-2;
        }
        int originalLength = originalArray.length;
        int newLength = originalLength - toDelete;
        int toChoose = newLength - 2;
        int[] newArray = new int[newLength];
        double fraction = ((double)toChoose) / ((double)originalLength -2);
        double counter = 0;
        int threshold = 1;
        int newArrayIndex = 1;
        for(int i = 1; i < originalLength-1; i++){
            counter += fraction;            
            if(((int)counter) == threshold ||
                //condition added to cope with x.99999999999999999... cases 
               (i == originalLength-2 && newArrayIndex == newLength-2)){
                newArray[newArrayIndex] = originalArray[i];
                threshold++;
                newArrayIndex++;
            }           
         }
         newArray[0] = originalArray[0];
         newArray[newArray.length-1] = originalArray[originalArray.length-1];
         return newArray;
    }
}

Why cant you just initialize i=0 为什么你不能初始化i=0

for (int i = 0; i < inputArr.length; i++) {
        if ((i + 1) % f != 0) {

Following is the output: 以下是输出:

arr[0]=1.0
arr[1]=1.0
arr[2]=3.0
arr[3]=5.0
arr[4]=7.0
arr[5]=9.0
arr[6]=11.0
arr[7]=13.0
arr[8]=15.0
arr[9]=16.0

如果我理解正确,这就是水库采样 ,即从一个大型阵列中,通过随机选择创建一个小型阵列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM