有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何对名称的字符串列表使用二级字母排序?

我正在尝试一种方法,当给定一个名为名字和姓氏的字符串时,名字被;分割,名字被:->

"Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill"

我想返回一个字符串,它将所有名字按大写字母排序,并根据姓氏和共享相同姓氏的人按字母顺序排序,然后在共享相同姓氏的人的名字之间再次排序(二级排序)。(我还特意将所有内容改为大写)

并返回排序名称的字符串,因此对于上面的示例,它应该返回:

"(CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)"

它根据姓氏的字母顺序进行排序,然后在拥有相同姓氏的人之间进行排序,第二类是名字

我设法进行了主要排序,即按字母顺序对姓氏进行排序,但我不确定如何进行第二次排序(在共享相同姓氏的人之间)。我曾想拆分成子数组或类似的东西,但我不知道如何做到这一点

解决这个问题的办法是什么

以下是我迄今为止管理的内容(主要排序工作):

public class Solution {
    public static String meeting(String s) {
        String m = "";
        List<String> name = new ArrayList<String>();
        for (String i : s.toUpperCase().split(";")) {
            String[] n = i.split(":");
            name.add(n[0] + " " + n[1]);
        }
        //main sorting
        java.util.Collections.sort(name);
        //secondary sorting and go through each different last name
        for (String i : name) {
            String[] n = i.split(" ");
            String lastname = n[1];
            // new list for the ppl who share same last name
            List<String> samel = new ArrayList<String>();
            samel.add(n[0]);
            for (String ss : name) {
                String[] nn = ss.split(" ");
                if (nn[1] == lastname) {
                    samel.add(nn[0]);
                }
            }
            //sort the ppl alphabetically with the same last name
            java.util.Collections.sort(samel);
        }
        for (String i : name) {
            String[] n = i.split(" ");
            m += ("(" + n[0] + " , " + n[1] + ")");
        }
        return m;
    }
}

我尝试进行二次排序,但未成功

如果我不够清楚的话,有两种排序方式,一种是按姓氏字母顺序进行的主排序,另一种是只对姓氏完全相同的人进行的次排序,然后根据字母顺序对他们的名字进行相应的排序。因此,如果我们有两个人叫matt cohn和mill cohn,那么他们的姓氏和姓氏中的第一个字母相同,但是a在o之前,所以输出应该是(COHN , MATT)(COHN, MILL),而不是相反

在下面的解决方案中,我运行了它并得到一个错误:

input String:
Alexis:Wahl;John:Bell;Victoria:Schwarz;Abba:Dorny;Grace:Meta;Ann:Arno;Madison:STAN;Alex:Cornwell;Lewis:Kern;Megan:Stan;Alex:Korn

Actual: (ARNO, ANN)(BELL, JOHN)(CORNWELL, ALEX)(DORNY, ABBA)(KERN, LEWIS)(KORN, ALEX)(META, GRACE)(STAN, MADISON)(SCHWARZ, VICTORIA)(STAN, MEGAN)(WAHL, ALEXIS)

Expect: (ARNO, ANN)(BELL, JOHN)(CORNWELL, ALEX)(DORNY, ABBA)(KERN, LEWIS)(KORN, ALEX)(META, GRACE)(SCHWARZ, VICTORIA)(STAN, MADISON)(STAN, MEGAN)(WAHL, ALEXIS)
false

但结果却是假的


共 (3) 个答案

  1. # 1 楼答案

    如果您使用的是Java stream,那么可以像这样使用sorted

    return Arrays.stream(s.split(";"))
            .map(p -> p.split(":"))
            .sorted(Comparator.comparing((String[] p) -> p[1]).thenComparing((String[] p) -> p[0]))
            .map(p -> String.format("(%s, %s)", p[1].toUpperCase(), p[0].toUpperCase()))
            .collect(Collectors.joining());
    

    输出

    (CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)
    

    我还建议使用对象而不是字符串来存储信息,使用这种方法不是一种好的做法

  2. # 2 楼答案

    您可以使用比较器链先按一个值排序,然后再按另一个值排序:

    String str = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;" +
            "Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";
    
    List<Map.Entry<String, String>> list = Stream.of(str)
            .map(String::toUpperCase)
            // Stream<String>
            .flatMap(s -> Arrays.stream(s.split(";")))
            // Stream<String[]>
            .map(s -> s.split(":"))
            // Stream<Map.Entry<String,String>>
            .map(arr -> Map.entry(arr[1], arr[0]))
            // sort by last name, then by first name
            .sorted(Map.Entry.<String, String>comparingByKey()
                    .thenComparing(Map.Entry::getValue))
            .collect(Collectors.toList());
    
    // output line by line
    list.forEach(System.out::println);
    

    输出:

    CORWILL=ALFRED
    CORWILL=FRED
    CORWILL=RAPHAEL
    CORWILL=WILFRED
    TORNBULL=BARNEY
    TORNBULL=BETTY
    TORNBULL=BJON
    

    另见:How to sort by a field of class with its own comparator?

  3. # 3 楼答案

    一种可能的解决方案如下:

    public class ExtractAndSortNames {
    
        public static String extractAndSort(String s) {
            return Stream.of(s.split(";"))
                    .map(String::toUpperCase)
                    .map(ExtractAndSortNames::extractPersonFirstNameAndLastName)
                    .sorted(Comparator.comparing(FirstNameAndLastName::getLastName).thenComparing(FirstNameAndLastName::getFirstName))
                    .map(FirstNameAndLastName::format)
                    .collect(Collectors.joining());
        }
    
        private static FirstNameAndLastName extractPersonFirstNameAndLastName(String personName) {
            var split = personName.split(":");
            var firstName = split[0];
            var lastName = split[1];
            return new FirstNameAndLastName(firstName, lastName);
        }
    
        private static class FirstNameAndLastName {
            private final String firstName;
            private final String lastName;
    
            public FirstNameAndLastName(String firstName, String lastName) {
                this.firstName = firstName;
                this.lastName = lastName;
            }
            
            public String getFirstName() {
                return firstName;
            }
            
            public String getLastName() {
                return lastName;
            }
            
            public String format() {
                return String.format("(%s, %s)", this.lastName, this.firstName);
            }
        }
    }
    

    无流的解决方案:

    public class ExtractAndSortNames {
    
        public static String extractAndSort(String s) {
            List<FirstNameAndLastName> toSort = new ArrayList<>();
            for (String s1 : s.split(";")) {
                String toUpperCase = s1.toUpperCase();
                FirstNameAndLastName firstNameAndLastName = extractPersonFirstNameAndLastName(toUpperCase);
                toSort.add(firstNameAndLastName);
            }
            toSort.sort(Comparator.comparing(FirstNameAndLastName::getLastName).thenComparing(FirstNameAndLastName::getFirstName));
            StringBuilder sb = new StringBuilder();
            for (FirstNameAndLastName firstNameAndLastName : toSort) {
                String format = firstNameAndLastName.format();
                sb.append(format);
            }
            return sb.toString();
        }
    
        private static FirstNameAndLastName extractPersonFirstNameAndLastName(String personName) {
            var split = personName.split(":");
            var firstName = split[0];
            var lastName = split[1];
            return new FirstNameAndLastName(firstName, lastName);
        }
    
        private static class FirstNameAndLastName {
            private final String firstName;
            private final String lastName;
    
            public FirstNameAndLastName(String firstName, String lastName) {
                this.firstName = firstName;
                this.lastName = lastName;
            }
    
            public String getFirstName() {
                return firstName;
            }
    
            public String getLastName() {
                return lastName;
            }
    
            public String format() {
                return String.format("(%s, %s)", this.lastName, this.firstName);
            }
        }
    }
    

    和测试:

    class ExtractAndSortNamesTest {
    
        @Test
        void test() {
            var input = "Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill";
            var result = ExtractAndSortNames.extractAndSort(input);
    
            assertEquals("(CORWILL, ALFRED)(CORWILL, FRED)(CORWILL, RAPHAEL)(CORWILL, WILFRED)(TORNBULL, BARNEY)(TORNBULL, BETTY)(TORNBULL, BJON)", result);
        }
    
        @Test
        void test2() {
            var input = "Alexis:Wahl;John:Bell;Victoria:Schwarz;Abba:Dorny;Grace:Meta;Ann:Arno;Madison:STAN;Alex:Cornwell;Lewis:Kern;Megan:Stan;Alex:Korn";
            var result = ExtractAndSortNames.extractAndSort(input);
    
            assertEquals("(ARNO, ANN)(BELL, JOHN)(CORNWELL, ALEX)(DORNY, ABBA)(KERN, LEWIS)(KORN, ALEX)(META, GRACE)(SCHWARZ, VICTORIA)(STAN, MADISON)(STAN, MEGAN)(WAHL, ALEXIS)", result);
        }
    }
    

    使用具有预览功能的Java 15进行奖励回合:

    public class ExtractAndSortNames {
    
        public static String extractAndSort(String s) {
            return Stream.of(s.split(";"))
                    .map(String::toUpperCase)
                    .map(FirstNameAndLastName::from)
                    .sorted(Comparator.comparing(FirstNameAndLastName::lastName).thenComparing(FirstNameAndLastName::firstName))
                    .map(FirstNameAndLastName::format)
                    .collect(Collectors.joining());
        }
    
        private static record FirstNameAndLastName (String firstName, String lastName) {
            private static FirstNameAndLastName from(String personName) {
                var split = personName.split(":");
                var firstName = split[0];
                var lastName = split[1];
    
                return new FirstNameAndLastName(firstName, lastName);
            }
    
            public String format() {
                return "(%s, %s)".formatted(this.lastName, this.firstName);
            }
        }
    }