4

I came up to a situation where I have an array and I need to copy some specific attributes (i.e. values at specific indinces) not the whole array to another array.

For example if the initial array is:

double[] initArray = {1.0, 2.0, 1.5, 5.0, 4.5};

then if I wanted to copy only 2nd, 4th and 5th attribute (i.e. values at these indices) the desired output array would be:

double[] reducedArray = {2.0, 5.0, 4.5};

I know that if the indices appear in a sequential form, e.g. 1-3 then I can use System.arraycopy() but my indices does not have that aspect.

So, is there any official way to do this, besides the trivial loop through each value and copy the ones needed:

double[] includedAttributes = {1, 4, 5};
double[] reducedArray = new double[includedAttributes.length];
for(int j = 0; j < includedAttributes.length; j++) {
    reducedArray[j] = initArray[includedAttributes[j]];
}
Community
  • 1
  • 1
Eypros
  • 5,370
  • 6
  • 42
  • 75
  • Is there any restrictions to using ArrayLists, for example? This way you could have an `ArrayList temp`, and then just add all the desired numbers there. After everything, you can get the `double[]` array by invoking `temp.toArray(new double[]{})`. You can do this with pure arrays too, of course. This is just a dirty, simple and easy method – Olavi Mustanoja Nov 27 '14 at 11:24
  • Java 8 Streams might be what you are looking for. Or is that Pre-8 ? – Fildor Nov 27 '14 at 11:27
  • @OlaviMustanoja although there is not any specific restriction, I would go for `ArrayList` due to autoboxing. – Eypros Nov 27 '14 at 12:14
  • @Fildor I am using Java 7 but anyway it could interesting to know this. – Eypros Nov 27 '14 at 12:15
  • Then maybe have a look here: http://stackoverflow.com/questions/18552005/is-there-a-concise-way-to-iterate-over-a-stream-with-indices-in-java-8 – Fildor Nov 27 '14 at 12:57

3 Answers3

2

Using streams, it's a one-liner.

Given:

int[] indices;
double[] source;

Then:

double[] result = Arrays.stream(indices).mapToDouble(i -> source[i]).toArray();
Bohemian
  • 412,405
  • 93
  • 575
  • 722
0

Simply said, its not possible, unless you have a specific case.

for example:

You want the top N items with highest value (in your case {2.0,4.5,5.0})

A quick(and dirty) way of doing it:

public static double[] topvalues(int n,double[] original){
 double[] output=new double[n];
 Arrays.sort(original);
 System.arraycopy(original,0,output,0,n);
 return output;
}

NOTE: this method also sorts your original array as well. if you don't want this behaviour there are different methods to use, here is a list of them :

nafas
  • 5,283
  • 3
  • 29
  • 57
0

Answering your question in a way perhaps not sought-after, you could write a class for this kind of operation:

public class PointerArray <T> {

    private T[] arr;
    private int[] indices;

    public PointerArray(T[] arr, int[] indices) {
        this.arr = arr;
        this.indices = indices;
    }

    public T get(int index) {
        return this.arr[this.indices[index]];
    }

    public void set(int index, T value) {
        this.arr[this.indices[index]] = value;
    }

    public int size() {
        return this.indices.length;
    }

}

This is untested code, but the idea in the very least should get through.

Using it would look something like this:

int[] includedAttributes = {0, 3, 4};

PointerArray<Double> reducedArray =
    new PointerArray<Double>(initArray, includedAttributes);

for(int j = 0; j < reducedArray.size(); j++) {
    System.out.println(reducedArray.get(j));
}

This is performance- and memory-wise, I think, a good solution, since nothing is copied (nor created). Only drawback is the need to call get(), but I have no idea how expensive method calls really are.

Olavi Mustanoja
  • 2,045
  • 2
  • 23
  • 34