0

the problem I encountered is not somewhat special, however, being relatively new to programming I find myself in a situation where I need some help from more advanced coders. The problem I have is sorting a list of objects, which have a varying size, based on their certain element. I have a set of data in picture below.

enter image description here

As you can see, the data consists 8 rows with different amount of string elements. My goal is to have these row objects sorted by columns.

What I mean - first, the rows are sorted by the first element of each row. So if the initial row arrangement according to the first elements of each row is [-2.2, 2.2, 2.2, -22, -22, -22, -1.1, qqqq], sorted arrangement would look like [-22, -22, -22, -2.2, -1.1, 2.2, 2.2, qqqq]. Then, since there are some rows with the same elements (0,1,2 row) and (5,6 row), these rows would be sorted by the second element - in this case, these second elements are 1234234, 11, -3 for rows with first element of -22 and 12345q, 12345q for rows with first element of 2.2.

After this, the two rows consisting 12345q as their second element would be sorted by third element, which for both are 69, and 4th elements would be reached (-afg and -asdf) which then would be sorted. The final result should look like on picture below

enter image description here

Now, I've done an extensive search on stackoverflow and the closest I would get to my case was Java sort based on two columns. I understand the steps I need to take in order to solve the probem (create a list, create a comparator etc.) but only in theory.

I have a List of Strings[] named rowObject, which contains all the rows with their respective string elements, whose amount, as I mentioned before, vary from row to row. I also have a comparator which does the sorting job exactly as it is needed, however, it is written in the compare method:

public class ComparatorClass {

public List compare(List<String> listOfValues) {
    Comparator<String> c = new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            boolean b1 = s1.matches(".*[^0-9.\\-].*");
            boolean b2 = s2.matches(".*[^0-9.\\-].*");

            // if both are gonna find doubles
            if (!b1 && !b2) {
                Double d1 = Double.parseDouble(s1);
                Double d2 = Double.parseDouble(s2);

                return d1.compareTo(d2);
            }
            // if both are text, then compare as strings
            else if (b1 && b2) {
                return s1.compareTo(s2);
            }
            // otherwise return one or the other, depending on which is text/number
            else return b2 ? -1 : 1;
        }
    };

    Collections.sort(listOfValues, c);
    return listOfValues;
}

Hence, I have a List of objects, which I need to sort according to their values, I have a Comparator, but I do not know how to put them all together to sort everything smoothly and in a gentle manner. I also do not know how to access the certain value of these objects in a good way, like String firstvalue = rowObject.get(i)[0] is pretty lame. Any help, advices, examples on how to glue everything together and produce the needed output is appreciated, thank you in advance.

xxxvodnikxxx
  • 1,270
  • 2
  • 18
  • 37
  • 1
    Possible duplicate of [Sort ArrayList of custom Objects by property](https://stackoverflow.com/questions/2784514/sort-arraylist-of-custom-objects-by-property) – daniu Apr 18 '18 at 09:15
  • What exactly *is* your problem? – HBo Apr 18 '18 at 09:20
  • The suggested topic by daniu probably has constructors involved with the getters, I dont know if I have to do something similar or can my case be solved by some other way @Hbo. Because if I had to set constructors for every row with different elements, it would get pretty confusing for me – Karolis Gadeikis Apr 18 '18 at 09:33

1 Answers1

1

It kind of depends on the data structure you have chosen. For example using arrays might be a bit harder to implement using the Comparator pattern. But if you have list of lists you can do it like that:

public class ComparatorClass implements Comparator<List<String>>{

            private int compare(String s1, String s2) {
                boolean b1 = s1.matches(".*[^0-9.\\-].*");
                boolean b2 = s2.matches(".*[^0-9.\\-].*");

                // if both are gonna find doubles
                if (!b1 && !b2) {
                    Double d1 = Double.parseDouble(s1);
                    Double d2 = Double.parseDouble(s2);

                    return d1.compareTo(d2);
                }
                // if both are text, then compare as strings
                else if (b1 && b2) {
                    return s1.compareTo(s2);
                }
                // otherwise return one or the other, depending on which is text/number
                else return b2 ? -1 : 1;
            }


        @Override
        public int compare(List<String> o1, List<String> o2) {
            for(int i=0;i<Math.min(o1.size(), o2.size()); i++) {
                int comparedAtThisLevel=compare(o1.get(i),o2.get(i));
                if(comparedAtThisLevel!=0)
                    return comparedAtThisLevel;
            }
            return Integer.compare(o1.size(),o2.size());
        }
    }

This is a comparator for list of strings (and not just for two strings). I used your method to compare the two strings on the same level but then I iterate through the list of values and compare 1st with 1st, 2nd with 2nd, 3rd with 3rd etc. If all values match (or one of the lists ends) we compare the sizes and take the longer one

Then you can test it with that:

public static void main(String[] args) {
        System.out.println(new Date()+": Let's start our StackOverflow helper project!");

        List<List<String>> listOfLists=new ArrayList<>();



            listOfLists.add(Arrays.asList("-22","123456","4234","5435345"));
            listOfLists.add(Arrays.asList("-22","-3","-4"));
            listOfLists.add(Arrays.asList("-22","11","Pillow"));

             Collections.sort(listOfLists, new ComparatorClass());           

}
Veselin Davidov
  • 7,031
  • 1
  • 15
  • 23