how to sort 2 arrays using java implement?

edited April 2017 in Questions about Code

I was trying to sort an array of object [] people, within each people object, I have 2 parameters, height and weight. I use JAVA script to sort height, using

int compareTo(Object objI)  
  {
    Individual iToCompare = (Individual) objI;  //cast object to individual
    if(height < iToCompare.height)
    {
      return -1;
    }
    else if(height > iToCompare.height)
    {
      return 1;
    }
    return 0;
  }

and then use

Arrays.sort(pop);

to sort my people according to height, but I also want another sort according to weight, how should I do that....?

Answers

  • edited April 2017 Answer ✓

    If your class implements Comparable then you have to add the compareTo method which provides natural ordering. For instance the words in a dictionary have a natural ordering and numbers have a natural ordering but a particular type (class) can only have one natural ordering.

    The solution is to create a special class that implements the Comparator interface. This classes will contain a single method to compare two objects in a similar way to compareTo. An object of the class is used by the Arrays.sort method to order the objects in the array.

    The advantage of this approach is that we can have as many comparators with different implementations used to compare objects.

    The code below produced this output and demonstrates the use of comparators.

    Unsorted array
    [0] Height: 1.9367965       Weight: 117.41198
    [1] Height: 1.8318218       Weight: 82.51117
    [2] Height: 2.097329        Weight: 106.100266
    [3] Height: 1.8637967       Weight: 116.23966
    [4] Height: 2.001055        Weight: 96.52715
    Sorted by WEIGHT
    [0] Height: 1.8318218       Weight: 82.51117
    [1] Height: 2.001055        Weight: 96.52715
    [2] Height: 2.097329        Weight: 106.100266
    [3] Height: 1.8637967       Weight: 116.23966
    [4] Height: 1.9367965       Weight: 117.41198
    Sorted by HEIGHT
    [0] Height: 1.8318218       Weight: 82.51117
    [1] Height: 1.8637967       Weight: 116.23966
    [2] Height: 1.9367965       Weight: 117.41198
    [3] Height: 2.001055        Weight: 96.52715
    [4] Height: 2.097329        Weight: 106.100266
    
    import java.util.*;
    
    Person[] people;
    
    // The comparators used for sorting
    Comparator<Person> weightCompare;
    Comparator<Person> heightCompare;
    
    void setup() {
      // Create some random Persons
      people = new Person[5];
      for (int i = 0; i < people.length; i++) {
        people[i] = new Person();
      }
      // Create the comparitor objects
      weightCompare = new WeightComparator();
      heightCompare = new HeightComparator();
    
      println("Unsorted array");
      printArray(people);
      println("Sorted by WEIGHT");
      Arrays.sort(people, weightCompare);
      printArray(people);
      println("Sorted by HEIGHT");
      Arrays.sort(people, heightCompare);
      printArray(people);
    }
    
    // Simple class to test the comparators
    class Person {
      float weight;
      float height;
    
      Person() {
        weight = random(80, 120);
        height = random(1.8, 2.2);
      }
    
      public String toString() {
        return "Height: " + height + "    \tWeight: " + weight;
      }
    }
    
    // Compare Persons based on their weight
    class WeightComparator implements Comparator<Person> {
    
      public int compare(Person ind1, Person ind2) {
        if (ind1.weight < ind2.weight)
          return -1;
        if (ind1.weight > ind2.weight)
          return 1;
        return 0;
      }
    }
    
    // Compare Persons based on their height
    class HeightComparator implements Comparator<Person> {
    
      public int compare(Person ind1, Person ind2) {
        if (ind1.height < ind2.height)
          return -1;
        if (ind1.height > ind2.height)
          return 1;
        return 0;
      }
    }
    
  • @quark thank you sooo much for your detailed explanation, I hardly know anything about java and know that I should have learnt it from textbook but there is little time for me.. I worked it out as your statements and it works pretty good! Thanks so much.

    Also many thanks to @GoToLoop and @kfrajer, I had looked through the forum as well as the java website and its very helpful for further self study!

  • @quark sorry for disturbing you again,,, but I was wondering is there a way to translate my object according to the sequence in two arrays I've got, for example, person A is the heaviest and the third tallest, so I want to

    translate (A's sequence in array[0], A's sequence in array [1]);

    I searched but not much results..

  • I am afraid I have no idea what you mean.

    Assuming that their are 10 people in the array, in other words in elements 0-9 incl. then -

    If person A is the heaviest person and the array is sorted by weight then they will be in element [9].

    If person A is the third tallest person and the array is sorted by height then they will be in the element [7].

    What do you mean by translate?

    You can have more than one array holding the same date like this

    import java.util.*;
    
    Person[] peopleByWeight, peopleByHeight;
    
    // The comparators used for sorting
    Comparator<Person> weightCompare;
    Comparator<Person> heightCompare;
    
    void setup() {
      // Create some random Persons
      Person[] people = new Person[5];
      for (int i = 0; i < people.length; i++) {
        people[i] = new Person();
      }
      // Create the 2 arrays we are interested in
      peopleByWeight = new Person[people.length];
      peopleByHeight = new Person[people.length];
      // Initialise both arrays
      arrayCopy(people, peopleByWeight);
      arrayCopy(people, peopleByHeight);
      // Create the comparitor objects
      weightCompare = new WeightComparator();
      heightCompare = new HeightComparator();
      // Sort the arrays by weight and by height
      Arrays.sort(peopleByWeight, weightCompare);
      Arrays.sort(peopleByHeight, heightCompare);
    
      println("Unsorted array");
      printArray(people);
      println("Sorted by WEIGHT");
      printArray(peopleByWeight);
      println("Sorted by HEIGHT");
      printArray(peopleByHeight);
    }
    
    // Simple class to test the comparators
    class Person {
      float weight;
      float height;
    
      Person() {
        weight = random(80, 120);
        height = random(1.8, 2.2);
      }
    
      public String toString() {
        return "Height: " + height + "    \tWeight: " + weight;
      }
    }
    
    // Compare Persons based on their weight
    class WeightComparator implements Comparator<Person> {
    
      public int compare(Person ind1, Person ind2) {
        if (ind1.weight < ind2.weight)
          return -1;
        if (ind1.weight > ind2.weight)
          return 1;
        return 0;
      }
    }
    
    // Compare Persons based on their height
    class HeightComparator implements Comparator<Person> {
    
      public int compare(Person ind1, Person ind2) {
        if (ind1.height < ind2.height)
          return -1;
        if (ind1.height > ind2.height)
          return 1;
        return 0;
      }
    }
    
  • @quark sorry for my confusing description..

    If person A is the heaviest person and the array is sorted by weight then they will be in element [9]. If person A is the third tallest person and the array is sorted by height then they will be in the element [7].

    then I'd like to translate A to (9interval,7interval);

  • 9 * interval, 7 * interval.

    don't know why the multiplication sign disappeared.

  • Still doesn't make sense what is 'interval'?

  • Are you taking about a 2D array?

  • @quark

    No..I'm talking about 2 arrays, sorted using the java class you've taught me. interval is just any integer, maybe 10...the important part is that it will be translated (9,7)

    I'll explain again..Since I have sort an array twice, for each individual, I now have 2 index for it, and I want to know the two index.

  • edited April 2017

    @vapeur -- an alternate approach:

    1. load your people data into a Table object https://processing.org/reference/Table.html
    2. sort by the height column https://processing.org/reference/Table_sort_.html
    3. add a new column "heightIndex" https://processing.org/reference/Table_addColumn_.html
    4. record the sorted index in each heightIndex, saving sort #1
    5. sort by the weight column
    6. add a column "weigthIndex"
    7. record the sorted index in each weigthIndex, saving sort #2

    Now regardless of future sorting or random lookups you can retrieve these values from any row you are accessing using getFloat() https://processing.org/reference/Table_getFloat_.html

      x = table.getFloat(row, "heightIndex");
      y = table.getFloat(row, "weigthIndex");
      translate(x,y);
    
  • edited April 2017

    @jeremydouglass thanks! I am working on it. but how to "record" the sorted index in each height index? not sure I'm doing the right thing...

    void calculation() { for(int i =0; i<num; i++) { calFit.setInt(i, "index", i); calFit.setFloat(i, "height",person[i].height ); calFit.setFloat(i, "weight", person[i].weight); } calFit.sort("height"); for(int i =0; i<num; i++) { calFit.setInt(i, "height index", i); } calFit.sort("weight"); for(int i =0; i<num; i++) { calFit.setInt(i, "weight index", i); } }

  • I can't test that code at the moment without a minimal complete example (and you should format your code in that post) however that does look correct.

    calFit.sort("weight");
    for(int i =0; i<num; i++) {
      calFit.setInt(i, "weight index", i);
    }
    

    When you are done you can use saveTable to inspect your data according to either sorting.

  • edited April 2017

    When you say translate, are you using their rankings to position some person graphic on the screen? For instance a persons x position is controlled by their height and their y position is controlled by their weight.

  • @jeremydouglass Thanks! I have no idea why it does not present as the code form, but I've already set it.. However, taken your advice it works totally fine! Thanks so much!

    @quark yes, I am using the ranking for the position of each person, showing on the screen. Though I made it with table class, I'd like to know other approach when you have time~

  • Answer ✓

    OK here is the output from the sketch code below. Notice that person A is the shortest and person E the heaviest.

    people

    import java.util.*;
    
    Person[] people, peopleByWeight, peopleByHeight;
    int gridSizeX, gridSizeY;
    
    // The comparators used for sorting
    Comparator<Person> weightCompare;
    Comparator<Person> heightCompare;
    
    void setup() {
      size(400, 400);
      textSize(12);
      textAlign(CENTER, CENTER);
      // Create some random Persons
      people = new Person[5];
      for (int i = 0; i < people.length; i++) {
        people[i] = new Person(i);
      }
      // How big is a grid square
      gridSizeX = width / people.length;
      gridSizeY = height / people.length;
    
      // Create the 2 arrays we are interested in
      peopleByWeight = new Person[people.length];
      peopleByHeight = new Person[people.length];
      // Initialise both arrays
      arrayCopy(people, peopleByWeight);
      arrayCopy(people, peopleByHeight);
      // Create the comparitor objects
      weightCompare = new WeightComparator();
      heightCompare = new HeightComparator();
      // Sort the arrays by weight and by height
      Arrays.sort(peopleByWeight, weightCompare);
      Arrays.sort(peopleByHeight, heightCompare);
    
      println("Unsorted array");
      printArray(people);
      println("Sorted by WEIGHT");
      printArray(peopleByWeight);
      println("Sorted by HEIGHT");
      printArray(peopleByHeight);
    
      // Display the empty grid
      drawEmptyGrid(people.length);
      // Display the peopl in the grid 
      // ^X = ^weight and ^Y = ^height
      drawPeople();
      save("people.png");
    }
    
    // Display the peopl in the grid based on their weight 
    // and height ranking
    void drawPeople() {
      for (Person p : people) {
        int weightRank = getRank(p, peopleByWeight);
        int heightRank = getRank(p, peopleByHeight);
        p.display(weightRank * gridSizeX, heightRank * gridSizeY);
      }
    }
    
    // Draw the basic empty grid.
    void drawEmptyGrid(int nbr) {
      background(0);
      fill(128);
      stroke(200);
      strokeWeight(2);
      int w = nbr * gridSizeX;
      int h = nbr * gridSizeY;
      rect(0, 0, w, h);
      for (int i = 0; i <= nbr; i++) {
        line(0, i * gridSizeY, w, i * gridSizeY); // Horz
        line(i * gridSizeX, 0, i * gridSizeX, h); // vert
      }
    }
    
    // Find the 'rank' (index position in array)
    int getRank(Person person, Person[] ranking) {
      for (int i = 0; i < ranking.length; i++) {
        if (person == ranking[i])
          return i;
      }
      return -1; // can't get here
    }
    
    // Simple class to test the comparators
    class Person {
      char name;
      float weight;
      float height;
    
      Person(int n) {
        name = (char)('A' + n);
        weight = random(80, 120);
        height = random(1.8, 2.2);
      }
    
      public void display(int x, int y) {
        stroke(0, 0, 128);
        strokeWeight(4);
        fill(200, 200, 255);
        rect(x, y, gridSizeX, gridSizeY);
        fill(0, 0, 96);
        String s = name + "\nH: " + nfp(height, 1, 2) + "\nW: " + nfp(weight, 3, 2);
        text(s, x, y, gridSizeX, gridSizeY);
      }
    
      public String toString() {
        return name + " : Height: " + height + "    \tWeight: " + weight;
      }
    }
    
    // Compare Persons based on their weight
    class WeightComparator implements Comparator<Person> {
    
      public int compare(Person ind1, Person ind2) {
        if (ind1.weight < ind2.weight)
          return -1;
        if (ind1.weight > ind2.weight)
          return 1;
        return 0;
      }
    }
    
    // Compare Persons based on their height
    class HeightComparator implements Comparator<Person> {
    
      public int compare(Person ind1, Person ind2) {
        if (ind1.height < ind2.height)
          return -1;
        if (ind1.height > ind2.height)
          return 1;
        return 0;
      }
    }
    
  • Thanks for the getrank function! is simple and great! :D

Sign In or Register to comment.