Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting an array by its values based on two arrays

I currently have 2 arrays, power and energy:

int[] power = [20, 10, 50, 10, 30, 5];
powerIndex     0   1   2   3   4   5
int[] energy = [20, 5, 15, 3, 10, 30];
energyIndex    0   1   2   3   4   5

I would like get an array with the indices of the power array sorted (lowest to highest), and in case the power number is the same, the power that uses less energy should get the first spot. So basically my desired output would be:

int[] result = [5, 3, 1, 0, 4, 2]

This is my code so far:

        int[] result = new int[power.length];
        int answerIndex = 0;
        int tempSmallest = Integer.MAX_VALUE;
        int lastNumberSaved = 0;
        int posWithSmallerPower = 0;


        while (answerIndex < power.length) {

            for (int i = 0; i < power.length; i++) {
                int current = power[i];
                if (tempSmallest > current && current > lastNumberSaved) {
                    tempSmallest = current;
                    posWithSmallerPower = i;
                }

                if (tempSmallest >= current && current > lastNumberSaved) {
                    if (current != lastNumberSaved && energy[posWithSmallerPower] > energy[i]) {
                        tempSmallest = current;
                        posWithSmallerPower = i;
                    }
                }
            }
            answer[answerIndex] = posWithSmallerPower;
            answerIndex++;
            lastNumberSaved = tempSmallest;
            tempSmallest = Integer.MAX_VALUE;
        }

        return answer;

What i'm getting: [5, 3, 0, 4, 2, 2]. And again, what I'm supposed to get: [5, 3, 1, 0, 4, 2]

I'm having trouble dealing with the powers that have the same number. I do compare them in the second array by their energy and I actually get the power in the index 3 first, but then the code completely forgots about the second power that also had the same number (10).

How do I achieve this? Thank you!

like image 971
fryecoding Avatar asked Oct 16 '22 08:10

fryecoding


2 Answers

This seems like a good use case for a temporary data structure that implements the Comparable interface. The javadoc for Comparable explains how this works pretty well but this is an example:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public final class Main {

    private static class Entry implements Comparable<Entry> {
        private final int power;
        private final int energy;
        private final int index;

        public Entry(int power, int energy, int index) {
            this.power = power;
            this.energy = energy;
            this.index = index;
        }

        @Override
        public int compareTo(Entry o) {
            if (this.power != o.power) {
                return this.power - o.power;
            }
            return this.energy - o.energy;
        }
    }

    public static void main(String[] args) {
        int[] power = {20, 10, 50, 10, 30, 5};
        int[] energy = {20, 5, 15, 3, 10, 30};

        List<Entry> entries = new ArrayList<>();
        for (int i = 0; i < power.length; i++) {
            entries.add(new Entry(power[i], energy[i], i));
        }

        Collections.sort(entries);
        List<Integer> result = entries.stream()
                .map(entry -> entry.index)
                .collect(Collectors.toList());
        System.out.println(result);
    }
}

Which outputs:

[5, 3, 1, 0, 4, 2]
like image 111
kingkupps Avatar answered Nov 04 '22 00:11

kingkupps


Used an inline Comparator<T> in list.sort() to compare the two powerEnergyIndex.

import java.util.ArrayList;
import java.util.List;

public class MainApplication {
    public static void main(String[] args) {
        int[] power = {20, 10, 50, 10, 30, 5};

        int[] energy = {20, 5, 15, 3, 10, 30};

        List<PowerEnergyIndex> powerEnergyIndices = new ArrayList<>();

        for(int i=0;i<power.length;i++) {
            powerEnergyIndices.add(new PowerEnergyIndex(power[i],energy[i],i));
        }

        powerEnergyIndices.sort((p1, p2)-> {
            if(p1.power!=p2.power) {
                return p1.power-p2.power;
            }
            return p1.energy-p2.energy;
        });

        int[] result = powerEnergyIndices.stream()
                                            .map(powerEnergyIndex -> powerEnergyIndex.index)
                                            .mapToInt(x->x)
                                            .toArray();

        for(int i:result) {
            System.out.print(i + " ");
        }



    }

    static class PowerEnergyIndex {
        private int power;
        private int energy;
        private int index;

        public PowerEnergyIndex(final int power, final int energy, final int index) {
            this.power = power;
            this.energy = energy;
            this.index = index;
        }
    }
}

which outputs 5 3 1 0 4 2

like image 34
Akshaya Kumar T Avatar answered Nov 03 '22 22:11

Akshaya Kumar T