0

I need to sort out the following array-

“Blouse” “W” 21 17.95
“Blouse” “C” 35 17.95
“Shirt”  “M” 13 21.95
“Pants”  “W” 22 67.95
“Pants”  “M” 22 62.95
“Pants”  “C” 26 21.95
“Coat”   “C” 20 21.95
“Coat”   “M” 10 62.95
“Blouse” “W” 21 17.95
“Blouse” “C” 35 17.95
“Shirt”  “M” 13 21.95
“Pants”  “W” 22 67.95
“Pants”  “M” 22 62.95
“Pants”  “C” 26 21.95
“Coat”   “C” 20 21.95
“Coat”   “M” 10 62.95

If the prices are same, I need to give priority to C before W, and W before M. I need to use selection sorting for this program, and it's as follows-

public static void selectionSort (Comparable[] list, int n)
{
    int min;
    Comparable temp;

    for (int i = 0; i< n - 1;i++)
    {
        min =  i;

        for(int scan = i + 1; scan < n; scan++)
        {
            if (list[i].compareTo(list[scan]) < 0)
                min = scan;
        }

       temp = list[min];
       list[min] = list[i];
       list[i] = temp;

    }

I am having problems when the prices are equal, my compareTo method is as follows. I am thinking of using sentinel values to give priority to these categories, but how would I do that? Also, what should the sorting algorithm do, having all these sentinel values for different categories while going through the whole array. How should it pick the proper (C before W, w before M) object to swap?

public int compareTo(Object obj)
{
    int result;
    double objPrice = ((Item)obj).getPrice();
    char objCategory = ((Item)obj).getCategory().charAt(1);

    if (objPrice == price)
    //         {
    //             if(objCategory.charAt(1) == 'M')
    //             return result = 0;
    //             else
    //             return result = 1;
    //         }
        switch (objCategory)
        {
            case 'C':
            return -1;
        }
    else
        return result = (int)(objPrice - price);

}
ScaVenGerS
  • 61
  • 1
  • 10
  • You could do two sort run throughs, one that sorts on price, the second will check for groups of equal values and re-sort those groups individually based on categories. – Christian Sarofeen Feb 21 '15 at 18:36

4 Answers4

0

Make a third field that holds priority of W M C and sort on multiple keys. Sorting Java objects using multiple keys

Community
  • 1
  • 1
Christian Sarofeen
  • 2,202
  • 11
  • 18
0

instead of the switch statement, you'll have to make if statements:

public int compareTo(Object obj)
{
    int result;
    double objPrice = ((Item)obj).getPrice();
    char objCategory = ((Item)obj).getCategory().charAt(1);

    if (objPrice == price) {
        if(category == objCategory) {
            return name.compareTo(((Item)obj).getName()); // if we have the same category, we need to decide somehow
        }
        if(category == "C") return 1; // C always beats everything
        if(objCategory == "C" ) return -1;

        if(category == "M") return -1; // M always looses
        if(objCategory == "M") return 1;
    } else {
        return result = (int)(objPrice - price);
    }

}

This does cover all 6 possible combinations of cetegories:

C - C => they are the same
C - W => one is C
C - M => one is C
W - C => one is C
W - W => they are the same 
W - M => one is M
M - C => one is C
M - W => one is M
M - M => they are the same
reckter
  • 586
  • 5
  • 12
  • If categories are the same we need to decide what? – ScaVenGerS Feb 21 '15 at 18:54
  • We need to decide what to return. And because all items have a name, I figured it would be best to sort them alphabetically then. If they do have the same price, category and name however, it will assume it is the same object. – reckter Feb 21 '15 at 19:04
0

Your compareTo is not complete. You need to compare the categories of the two items.

Inside the if (objPrice == price) add something like:

if (objCat == 'C')
      return cat == 'C' ? 0 : -1

  if (objCat == 'W')
      return cat == 'C' 
         ? 1
         : (cat == 'W')
            ? 0
            : -1

  if (objCat == 'M')
     ... Check for three possibilities

To simplify the comparison, add a mapping from category to an integer (e.g. Using a map). This will make your comparison look more like this:

if (objPrice == price)
   return mappedValueOf(cat1) - mappedValueOf(cat2)
amahfouz
  • 2,328
  • 2
  • 16
  • 21
0

If you are using you can use the Streaming API:s combined with Comparator.comparing and Comparator.thenComparing to make the sorting work.

If you assume the following Item class:

public class Item {
    private final String category;
    private final String name;
    private final double price;
    private final int size;

    public Item(
            final String name, 
            final String category, 
            final int size, 
            final double price) {

        this.name = name;
        this.category = category;
        this.size = size;
        this.price = price;
    }

    public String getCategory() {
        return category;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public int getSize() {
        return size;
    }

    @Override
    public String toString() {
        return "Item: [" +
                Objects.toString(name) + " " +
                Objects.toString(category) + " " +
                Objects.toString(price) + " " +
                Objects.toString(size) + "]";
    }
}

Then, the sorting can be done like this:

final List<Item> items = Arrays.asList(
        new Item("Blouse", "W", 21, 20.95),
        new Item("Blouse", "W", 21, 17.95),
        new Item("Blouse", "M", 21, 17.95),
        new Item("Blouse", "C", 21, 17.95));

final List<String> categoryPrioOrder = Arrays.asList("C", "W", "M");

final List<Item> sorted = items.stream()
        .sorted(Comparator.comparingDouble(Item::getPrice)
                .thenComparing(
                        Item::getCategory,
                        (c1, c2) -> categoryPrioOrder.indexOf(c1) - categoryPrioOrder.indexOf(c2)))
        .collect(Collectors.toList());

System.out.println(sorted);

The output will be (as per the OPs specification):

[Item: [Blouse C 17.95 21], Item: [Blouse W 17.95 21], Item: [Blouse M 17.95 21], Item: [Blouse W 20.95 21]]

wassgren
  • 18,651
  • 6
  • 63
  • 77