views:

208

answers:

3

Hey, I need to sort an array list of class house by a float field in a certain range. This is my code for the selection sort: Basically sortPrice copies the stuff in this list into a new one selecting only the values in that range, then it does a selection sort in that array list. The arraylist (x) in sortPrice is unsorted an needs to be copied because what x references cannot be altered.

public ArrayList<House> sortPrice(ArrayList<House> x,float y, float z){
    ArrayList<House> xcopy = new ArrayList<House>();
    for(int i = 0; i<x.size(); i++){
        if(x.get(i).myPriceIsLessThanOrEqualTo(z) && x.get(i).myPriceIsGreaterThanOrEqualTo(y)){
            xcopy.add(x.get(i));
        }
    }

    ArrayList<House> price= new ArrayList<House>();
    while(xcopy.size()>0){
        House min = xcopy.get(0);
        for(int i = 1; i < xcopy.size();i++){
            House current = xcopy.get(i);
            if (current.myPriceIsGreaterThanOrEqualTo(min.getPrice())){
                min = current;
            }
        }
        price.add(min);
        xcopy.remove(min);
    }
    return price;
}

Here is what the house class looks like:

public class House {
private int numBedRs;
private int sqft;
private float numBathRs;
private float price;
private static int idNumOfMostRecentHouse = 0;
private int id;

public House(int bed,int ft, float bath, float price){
    sqft = ft;
    numBathRs = bath;
    numBedRs = bed;
    this.price = price;
    idNumOfMostRecentHouse++;
    id = idNumOfMostRecentHouse;
}



public boolean myPriceIsLessThanOrEqualTo(float y){
    if(Math.abs(price - y)<0.000001){
        return true;
    }
    return false;
}
public boolean myPriceIsGreaterThanOrEqualTo(float b){
    if(Math.abs(b-price)>0.0000001){
        return true;
    }
    return false;
}

When i call looking for houses in range 260000.50 to 300000 I only get houses that are at the top of the range even though I have a lower value at 270000. Can someone help?

A: 

You should use rounded double type.

DecimalFormat p= new DecimalFormat( "#0.00" );
double price = 123.00001;
price = new Double(p.format(price)).doubleValue();
sza
I am a first year student and am restricted to certain code. My teachers test code would probably mark me down in those sections. The options given to me are Math.abs( x-y ) < 0.000001If the above boolean expression is true, then consider x and y equal.# int x1 = Float.floatToIntBits(x);int y1 = Float.floatToIntBits(y);Math.abs (x1-y1 ) <= 2If the above boolean expression is true, then consider x and y equal.
This is kinda funny. I really don't understand that if you are not dealing with a pure algorithm theory problem, why your teacher didn't allow you guys to use some canonical software engineering solution? I believe using the SE way to think about the problem is far more useful than sort of tricky mathematics. Even if you want to do it in theoretical way, you should never use 0.0000001, which is still not precise. You should use Float.MIN_VALUE instead...
sza
A: 

The best data structure for this problem would be a NavigableMap<Float,List<House>> (such as a TreeMap), which supports a subMap operation:

SortedMap<K,V> subMap(K fromKey, K toKey) : Returns a view of the portion of this map whose keys range from fromKey, inclusive, to toKey, exclusive.

There is also an overload that allows you to set inclusive bounds.

Here's a demonstration:

    NavigableMap<Integer,String> nmap = new TreeMap<Integer,String>();
    nmap.put(5, "Five");
    nmap.put(1, "One");
    nmap.put(7, "Seven");
    nmap.put(3, "Three");

    System.out.println(nmap.subMap(2, 6));
    // prints {3=Three, 5=Five}

For your case, you'd want to either make House implementsComparable<House>, or define your own custom Comparator<House>. You'd then let TreeMap do the sorting for you, and don't have to deal with selection sort (which, at O(N^2), is far from optimal).


If you're stuck with the specification that you're given, then I'd suggest breaking apart the logic into helper methods like these:

List<House> filterInRange(List<House> houses, float low, float high) {
   List<House> ret = new ArrayList<House>();
   for (House h : houses) {
      if (isInRange(h.getPrice(), low, high)) {
         ret.add(h);
      }
   }
   return ret;
}

static boolean isInRange(float v, float low, float high) { ...DIY... }

void selectionSort(List<House> houses) { ...Wikipedia... }

Then to get a sorted List<House> in a specified price range, invoke filterInRange and then selectionSort the returned list.

See also

polygenelubricants
A: 
  1. Your method name indicates it sorts the data, the method also filters. You need to change the name. Actually there are a number of variables in this code which need their names change to better reflect what they contain.

  2. You need to replace the for loops with for-each loops. That will simply and make the code clearer. You would also no longer need the while() statement.

  3. I would also refactor the mypriceis... methods into a single ispriceinrange method.

  4. Alternatively I'd look at the comparator interface and look at introducing it as a way to sort you data without having to hand code a loop.

  5. Just took a second look. You do actually sort in the second loop, but that some ugly code and probably won't perform well to boot. Definitely go look at comparator and Collections.sort() methods. Save yourself a world of pain.

Derek Clarkson