Use same sorting algorithm with different attributes

Asked

Viewed 112 times

1

Setting:

I am developing a small application as a task of my course. As the intention of the work is precisely to show what we learned during the classes, I can not escape much of what I already have, better to say, I can not leave for "very advanced things". Although I know it’s naturally complicated to do what I want, I want tips in "simple" ways to do it.

At a certain point I need to sort a collection of users by their wins (from the largest pro minor), using as tie-breaker its defeats (the less defeats, the higher). The class Usuario has both attributes (vitorias and derrotas).

What I want to do is also the ordination of array for amount of defeats user, however, without having to rewrite this entire method.

My current sorting method is as follows (the sorting algorithm used is the Bubble Sort)

private void ordenar(Usuario[] usuarios){
    boolean troca = true;

    while(troca){            
        troca = false;
        for(int i = 0; i < usuarios.length - 1; i++) {
            if(usuarios[i].getVitorias() < usuarios[i + 1].getVitorias() || 
               (usuarios[i].getVitorias() == usuarios[i + 1].getVitorias()
                && usuarios[i].getDerrotas() > usuarios[i + 1].getDerrotas()))
            {
                Usuario u = usuarios[i + 1];
                usuarios[i + 1] = usuarios[i];
                usuarios[i] = u;
                troca = true;
            }
        }
    }
}

2 answers

3

Good afternoon, according to your code, I believe that the simplest way to make the attribute-based Sort would be more or less this way:

Create an Enum for fields that can be ordered

public enum ESort {
    VITORIAS, DERROTAS;
}

Create an Enum for the sorting side

public enum EOrder {
    ASCENDENTE, DESCENDENTE;
}

Created these two Enum’s you will need to change your sorting method to work with these variances.

Now you will need to create a method that validates the exchange by order

public boolean isTrocaOrder(int x1, int y1, int x2, int y2, EOrder order) {
    if (order == EOrder.DESCENDENTE) {
        if (x1 < x2 || (x1 == x2 && y1 > y2)) {
            return true;
        }
    } else if (order == EOrder.ASCENDENTE) {
        if (x1 > x2 || (x1 == x2 && y1 < y2)) {
            return true;
        }
    }
    return false;
}

I created separately the field calls

private boolean isTrocaDerrotas(Usuario prev, Usuario next, EOrder order) {
    return isTrocaOrder(prev.getDerrotas(), prev.getVitorias(), next.getDerrotas(), next.getVitorias(), order);
}

private boolean isTrocaVitorias(Usuario prev, Usuario next, EOrder order) {
    return isTrocaOrder(prev.getVitorias(), prev.getDerrotas(), next.getVitorias(), next.getDerrotas(), order);
}

another step is to create a field validator

private boolean isTrocaCampo(Usuario prev, Usuario next, ESort sort, EOrder order) {
    if (sort == ESort.VITORIAS) {
        return isTrocaVitorias(prev, next, order);
    } else if (sort == ESort.DERROTAS) {
        return isTrocaDerrotas(prev, next, order);
    }
    return false;
}

Now your method can be changed

private void ordenar(Usuario[] usuarios, ESort sort, EOrder order) {
    boolean troca = true;

    while (troca) {
        troca = false;
        for (int i = 0; i < usuarios.length - 1; i++) {
            Usuario prev = usuarios[i];
            Usuario next = usuarios[i + 1];
            if (isTrocaCampo(prev, next, sort, order)) {
                usuarios[i + 1] = prev;
                usuarios[i] = next;
                troca = true;
            }
        }
    }
}

I believe that in this way you can reuse in various ways your method, example of calls:

ordenar(usuarios, ESort.VITORIAS, EOrder.DESCENDENTE);
ordenar(usuarios, ESort.VITORIAS, EOrder.ASCENDENTE);
ordenar(usuarios, ESort.DERROTAS, EOrder.DESCENDENTE);
ordenar(usuarios, ESort.DERROTAS, EOrder.ASCENDENTE);

recalling that this code is using the Bubble Sort sorting method. If you need to use other sorting methods as well you can create an interface ITipoOrdenacao for example with the method sort and amend the methods as required.

I hope I’ve helped Hug

  • Good! I liked the solution.

2


Use an interface

One of the ways you change the sorting function is through the use of an interface. Following the code you have already written, without modifying the way you are doing Sort, an interface suggestion would be as follows:

interface Comparador 
{
    boolean compare(Usuario a, Usuario b);
}

You could write two implementations for it, for example:

One to order for victories:

class Vitoriosos implements Comparador {
    public boolean compare(Usuario a, Usuario b) {
        return (a.getVitorias() < b.getVitorias() ||    
           (a.getVitorias() == b.getVitorias()
           && a.getDerrotas() > b.getDerrotas()));
    }
}   

Another to order through defeat:

class Derrotados implements Comparador {
    public boolean compare(Usuario a, Usuario b) {
        return (a.getDerrotas() < b.getDerrotas() ||    
          (a.getDerrotas() == b.getDerrotas()
          && a.getVitorias() > b.getVitorias()));
    }
}   

The modification in your code would be for you to pass, in addition to the collection of users, the instance of the class that implements the interface. It would look something like:

private static void ordenar(Usuario[] usuarios, Comparador cmp){
    boolean troca = true;

    while(troca){            
        troca = false;
        for(int i = 0; i < usuarios.length - 1; i++) {
            if(cmp.compare(usuarios[i], usuarios[i+1]))
            {
                Usuario u = usuarios[i + 1];
                usuarios[i + 1] = usuarios[i];
                usuarios[i] = u;
                troca = true;
            }
        }
    }
}

In Java and other languages there is a similar way to create classes of comparators. In Java, the corresponding interface calls Comparator. On this page has a very simple tutorial explaining the Comparator and the Comparable.

  • Great! It really looks like a very good and extremely simple exit. I think I missed coffee today and I messed up what I didn’t need. Thanks!

  • I tried not to change the line you’d already started.

  • Got too good, thanks again.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.