如何根据输入值和用户输入的升序/降序执行自定义排序-Java

ha5z0ras  于 2023-01-11  发布在  Java
关注(0)|答案(3)|浏览(127)

我试图找到一个与排序相关的问题的解决方案。输入是一个值列表,其中列表中的每个值都是包含两个String值{name,id}的列表。示例输入列表如下所示

{{name99,id1},{name2,id2},{name36,id3}}

我的要求是基于输入排序条件和排序顺序对这些进行排序。如果排序条件是“name”,输入顺序标准是 asc,那么我的输出列表应该是:

{{name2,id2},{name36,id3},{name99,id1}}

如果排序条件是“id”,以 desc 作为输入顺序条件,则输出列表应该是:

{{name36,id3},{name2,id2},{name99,id1}}

到目前为止所完成的实现并没有按照我使用compareTo时的预期对字符串进行排序

List<String> sample1= Arrays.asList("name99","id1");
        List<String> sample2= Arrays.asList("name1","id12");
        List<String> sample3= Arrays.asList("name22","id99");
        List<String> sample4= Arrays.asList("name36","id5");
        List<String> sample5= Arrays.asList("name343","id3");
        List<List<String>> items=Arrays.asList(sample1,sample2,sample3,sample4,sample5);
        String sortOrderVal="asc";
        String sortParamVal="name";
        int sortParameter="name".equalsIgnoreCase(sortParamVal)?0:1;
        sortBasedonInput(items,sortOrderVal,sortParameter);

    }
    
    
    private static void sortBasedonInput(List<List<String>> items, String sortOrder, int sortParameter) {
        System.out.println("before sort: "+items);
            for(int j=0;j<items.size();j++) {
                for(int i=0;i<items.size()-1;i++) {
                    if(items.get(i).get(sortParameter).compareTo(items.get(i+1).get(sortParameter))>0) {
                        List<String> temp=items.get(i);
                        items.set(i,items.get(i+1));
                        items.set(i+1,temp);
                    }
                }}
            if("asc".equalsIgnoreCase(sortOrder))
                System.out.println(items);
            else {
                Collections.reverse(items);
                System.out.println(items);
            }
            
    }

按升序排列的name的实现输出:排序前:

[[name99, id1], [name1, id12], [name22, id99], [name36, id5], [name343, id3]]

排序后:

[[name1, id12], [name22, id99], [name343, id3], [name36, id5], [name99, id1]]

注意:名称为343的项目位于名称为36的项目之前

3npbholx

3npbholx1#

下面显示了用于排序的比较器,然后显示了使用比较器的泛型方法,以及排序顺序应该是desc还是asc。

public static void main(String[] args) {
        List<String> item1 = Arrays.asList("name99","id1");
        List<String> item2 = Arrays.asList("name2","id2");
        List<String> item3 = Arrays.asList("name36","id3");
        List<List<String>> listOfLists = Arrays.asList(item1, item2, item3);
        
        Comparator<List<String>> nameComparator = (l1, l2) -> l1.get(0).compareTo(l2.get(0));
        Comparator<List<String>> idComparator = (l1, l2) -> l1.get(1).compareTo(l2.get(1));
        //sort by name in asc
        listOfLists.sort(nameComparator);
        System.out.println(listOfLists);
        //instead of making a new comparator with l2 compared to l1, just call comparator.reversed()
        listOfLists.sort(nameComparator.reversed());
        System.out.println(listOfLists);
        //testing out generic method to pass list of lists, sort comparator and the ordering of the sort.
        sortListByComparatorAndOrder(listOfLists, idComparator, "DESC");
        System.out.println(listOfLists);
        
    }
    //generic method to sort a list 
    public static <T> void sortListByComparatorAndOrder(List<T> listToSort, Comparator<T> sorter, String order) {
        if (order.equals("ASC")) {
            listToSort.sort(sorter);
        }else if (order.equals("DESC")) {
            listToSort.sort(sorter.reversed());
        }
    }

输出:

[[name2, id2], [name36, id3], [name99, id1]]
[[name99, id1], [name36, id3], [name2, id2]]
[[name36, id3], [name2, id2], [name99, id1]]

您还可以使用以下不使用泛型并遵循方法签名的方法:

public static void sortListByGivenIndexAndOrder(List<List<String>> listToSort, int index, String order) {
        Comparator<List<String>> indexComparator = (l1, l2) -> l1.get(index).compareTo(l2.get(index));
        if (order.equals("ASC")) {
            listToSort.sort(indexComparator);
        }else if (order.equals("DESC")) {
            listToSort.sort(indexComparator.reversed());
        }
    }

特别说明:考虑到name中有整数,我怀疑这种逻辑可能不是一个好主意。虽然name2在name36之前,但name2不会在name16之前,所以我认为这可能不是比较器的最佳逻辑。
如果id是数字的字符串表示,即“9”“10”,而不是字母表和数字的混合“id9”“id10”,您可以改为解析字符串中的数字,以避免上述注解中提到的问题,即:

Comparator<List<String>> idComparator = (l1, l2) -> {
            Integer val1 = Integer.parseInt(l1.get(1));
            Integer val2 = Integer.parseInt(l2.get(1));
            return val1.compareTo(val2);
        };
8mmmxcuj

8mmmxcuj2#

你可以使用apache的org.apache.commons.lang3.tuple.Pair来建模它,这应该涵盖所有4种情况:

List<Pair<String, String>> list = new ArrayList<>();
list.add(new MutablePair<>("name99", "id1"));
list.add(new MutablePair<>("name2", "id2"));
list.add(new MutablePair<>("name36", "id3"));
    
list.sort(Comparator.comparing(Pair::getLeft));// name, asc
list.sort(Comparator.comparing(Pair::getLeft, Collections.reverseOrder()));// name, desc
list.sort(Comparator.comparing(Pair::getRight)); // id, asc
list.sort(Comparator.comparing(Pair::getRight, Collections.reverseOrder())); // id, desc
bxjv4tth

bxjv4tth3#

对于给定的样本输入,即:所有项目都以nameid为前缀,仅在末尾附加的数字上有所不同,类似于以下内容应起作用:

  • 创建一个函数来删除所有非数字字符并解析为int
  • 创建一个比较器,并从给定的参数中选择正确的索引进行比较
  • 如果需要,反转排序顺序

代码:

private static void sortBasedonInput(List<List<String>> items, String sortOrder, int sortParameter) {

    Function<String,Integer> func = str -> Integer.parseInt(str.replaceAll("\\D+", ""));
    Comparator<List<String>> sortBy = Comparator.comparingInt(list -> func.apply(list.get(sortParameter)));
    if (sortOrder.equals("desc")){
        sortBy = sortBy.reversed();
    }
    items.sort(sortBy);
}

相关问题