We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › sort array of objects by String inside variable
Pages: 1 2 
sort array of objects by String inside variable (Read 2471 times)
sort array of objects by String inside variable
Jan 4th, 2009, 6:14am
 
i have an array of objects from a custom class with a property/attribute/field( I really dont know what to call it) that was fed via an argument in the constructor, and I would like to sort my objects in this list according to this String. I have no idea where to begin with this one. Found a lead on a comparator but it was a bit over my head and I'm not even quite sure it's what I want.

Can anyone give me any leads?

thanks!
Re: sort array of objects by String inside variabl
Reply #1 - Jan 4th, 2009, 8:50am
 
There is a Java utility class called Arrays that has a sort() method that will do what you want.

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Arrays.html#sort(java.lang.Object[],%20int,%20int,%20java.util.Comparator)

You would have to write the Comparator class, since it sounds like you aren't sorting by the natural order of the class.

Comparators really aren't that hard to write. You need to create a class that implements the Comparator interface.

Here's some sample code I whipped up to demonstrate.


class A {
 String str;
 // Constructor just sets the value of str
 A(String s) {
   str = s;
 }
 // Returns str
 String getStr() {
   return str;
 }
 // Override toString so the value of str is shown by println()
 String toString() {
   return str;
 }
}

class AComparator implements Comparator {
 int compare(Object o1, Object o2) {
   String str1 = ((A) o1).getStr();
   String str2 = ((A) o2).getStr();
   return str1.compareTo(str2);
 }
}

// Create an array with 3 A objects that are not sorted by the str field
A a1 = new A("abcd");
A a2 = new A("efgh");
A a3 = new A("cdef");
A[] aArray = new A[] {a1, a2, a3};

// Print the array to show array is not in sorted order
println(aArray);
println();

// Sort and print to show array is now sorted by the value of str
Arrays.sort(aArray, new AComparator());
println(aArray);
Re: sort array of objects by String inside variabl
Reply #2 - Jan 4th, 2009, 12:35pm
 
Good example!
An alternative is to use the Comparable interface. See java.util.Comparable vs java.util.Comparator for an explanation on the differences (but that's java.lang.Comparable).
Looks like there is a good article at Java Sorting: Comparator vs Comparable Tutorial too (not read yet).
Re: sort array of objects by String inside variabl
Reply #3 - Jan 23rd, 2009, 11:09pm
 
thanks so much WombatNation! I just finally implemented it and it's working just fine

here's a question about taking it further - say I have sorted my array by a certain attribute but there are other attributes which I would like to sort each of those groupings by would I need to create separate arrays from the first and do another comparator? Is there a way to split the array at the point where the attribute changes?

for a concrete example - I have 70 or so animals and I want to sort by the biome in which they're found - and I have done that easily thanks to your help - but then within each biome(my initial sorting key) within the array I want the animals to be grouped by a diet type( a second layer of sorting), how would I do this...

Re: sort array of objects by String inside variabl
Reply #4 - Jan 24th, 2009, 11:00am
 
You just have to adapt the compare function.
To reuse above code:
Code:
class AComparator implements Comparator {
 int compare(Object o1, Object o2) {
   String b1 = ((A) o1).getBiome();
   String b2 = ((A) o2).getBiome();
   if (b1.equals(b2)) {
     // Identical biomes, compare the diet
     String d1 = ((A) o1).getDiet();
     String d2 = ((A) o2).getDiet();
     return d1.compareTo(d2);
   } else {
     // Just compare the biomes
     return b1.compareTo(b2);
   }
 }
}
(untested)
(PS.: Official term for class variables is "fields".)
Re: sort array of objects by String inside variabl
Reply #5 - Jan 26th, 2009, 1:15am
 
i tried to use a float comparison instead of the string comparison in the nested check and I got an error:

"Cannot invoke compareTo(float) on the primitive type float"

Quote:
class SortBySpecials implements Comparator {
  int compare(Object o1, Object o2) {
    String str1 = ((Icon) o1).getSpecial();
    String str2 = ((Icon) o2).getSpecial();
    
     if (str1.equals(str2)) {
      
      float d1 = ((Icon) o1).getArea();
      float d2 = ((Icon) o2).getArea();
      return d1.compareTo(d2);
      
    } 
    else {
    
    return str1.compareTo(str2);
    }
  }




Also, once my array is sorted how do I trigger a different behaviour for a shift in the field value - say I am cycling through my array assigning each a field value but I want something different to happen at each change in the field value I used to sort my data, how would I do this...? I think I may be going about this the wrong way...I am trying to plot out my array objects (animals) in a 2d graph but in such a way so that they do not overlap, and for that I have been using a distinct int count++ for every possible region of the graph so each animal gets neatly plotted one after the next...

how do I fix this? Thanks for your help!
Re: sort array of objects by String inside variabl
Reply #6 - Jan 26th, 2009, 5:54am
 
Since a float (with lowercase 'f') is a primitive type, it does not inherit from java.lang.Object. Therefore, it doesn't have methods.

With primitives, you use operators like >, ==, >=, etc. for comparisons.

Java provides object versions of all the primitives, though. You can easily construct a Float object from a float primitive.

Something like:

Float d1 = new Float(((Icon) o1).getArea());
Float d2 = new Float(((Icon) o2).getArea());
return d1.compareTo(d2);

However, if you were worried about performance, it would make more sense to directly implement the compareTo behavior for float primitives.

return (d1<d2) ? -1 : (d1==d2) ? 0 : 1;

A little more cryptic, but I think that would do the job.
Re: sort array of objects by String inside variabl
Reply #7 - Jan 26th, 2009, 6:12am
 
Also, sorry, but I didn't quite follow your second question. Either I'm missing an important piece of context or I've just had too many glasses of Syrah tonight.
Re: sort array of objects by String inside variabl
Reply #8 - Jan 26th, 2009, 11:14pm
 
no problem - it is completely my inability to explain what it is I'm after. that's partly because my target is moving.

what I was getting at was how to use the newly sorted array for a situation where items are being drawn in a sequence. If a field value changes from let's say one biome to another within the array of items I was thinking that this could trigger a different action. Let's say I have five columns for five biomes and I want to place each animal in their respective biome column, the question was could I use the newly sorted list and somehow get the shift in column to coincide with a shift in biome field value. I have been relying on integers which I am iteratively adding to each time an animal is placed in a column so that they can be drawn in any order and no two will overlap...perhaps I should post the applet...

and back to the nested loop - I am getting a NullPointerException on the if (str1.equals(str2)) line...this doesn't seem to have anything to do with my desire to compare floats - I tried it with another string...

thanks again!
Re: sort array of objects by String inside variabl
Reply #9 - Jan 26th, 2009, 11:52pm
 
oompa_l wrote on Jan 26th, 2009, 11:14pm:
I am getting a NullPointerException on the if (str1.equals(str2)) line...
That means that str1 is null, ie. not initialized. Are you sure all your fields are set correctly
Re: sort array of objects by String inside variabl
Reply #10 - Jan 27th, 2009, 12:13am
 
oops. yeah. I have done so many of these half sketches some with things I am keeping others that have progresed but lacking in the improvements...anyways I am terrible at keeping my work ordered. so it worked just fine.

is there a way to make it go from biggest to smallest, or to change the order of the field values? it's not critical, but since we're already on the topic i thought I should ask.

thanks so much
Re: sort array of objects by String inside variabl
Reply #11 - Jan 27th, 2009, 10:48am
 
oompa_l wrote on Jan 27th, 2009, 12:13am:
is there a way to make it go from biggest to smallest

Just invert the result of the Comparator.
You can do whatever you want here, compare a string starting at nth character or after the nth comma, comparing reversed strings or in case-insensitive way, etc. Just process the strings (or objects) before comparing them.
Re: sort array of objects by String inside variabl
Reply #12 - Feb 8th, 2009, 2:20pm
 
I have a ArrayList called linesCopy, in which a certain amount of lines is added. These lines all have a certain angle, which I have a void for in the class Line (line.getAnglePG). Now I want the lines to be sorted according to these angles.

Q1: solved, see UPDATE below
Q2: solved, see UPDATE below



This is the code in the draw() void:
-----------------------------------
linesCopy = new ArrayList();
for (int j=0; j<lines.size(); j++)
 L = (Line) lines.get(j);
 if (L.ID1 == N1.ID) {
   linesCopy.add(L);
 }
}
Arrays.sort(linesCopy, new SortByAnglePG());
---------------------------------------------



Code for the corresponding class SortByAnglePG:
-----------------------------------------------
class SortByAngleDG implements Comparator {
 int compare(Object o1, Object o2) {
   float angle1 = -( (Line) o1).getAnglePG());
   float angle2 = -( (Line) o2).getAnglePG());
   return (angle1<angle2) ? -1 : (angle1==angle2) ? 0 : -1;
 }
}
-----------------------------------------------



UPDATE
Q1: found out myself: instead of 'Arrays.sort()' I have to use 'Collections.sort()'.
TIP: use Collections.sort() for ArrayLists and Arrays.sort() for array[]'s.

Q2: as stated in an earlier post about primitives, objects and floats. The minus-trick works perfectly for me.
Re: sort array of objects by String inside variabl
Reply #13 - Feb 22nd, 2009, 11:01pm
 
@Wombat - this is a very useful explanation, thanks.

Quote:
However, if you were worried about performance, it would make more sense to directly implement the compareTo behavior for float primitives.

return (d1<d2) ? -1 : (d1==d2) ? 0 : 1;


Why is that faster than compareTo?  you mean because you don't have to create objects (i.e. you can use float instead of Float)?

@TVS: curious what your exact Q1 and Q2 were, which you have replaced with "solved," i can guess from the solution update but update Q2 is cryptic.    
Re: sort array of objects by String inside variabl
Reply #14 - Feb 23rd, 2009, 6:09am
 
@Eric F.: Correct. There is a little extra work in creating the objects and then garbage collecting them.

I generally lean toward clarity of code at the cost of some performance, unless I've proven to myself that there is a real performance issue. And then I make sure I include a comment explaining why I've written the code that way.
Pages: 1 2