如何对名称的字符串列表使用二级字母排序?
How to use a secondary alphabetical sort on a string list of names?
我正在尝试一种方法,当给定一串名字(名字和姓氏)时,名字被 ;
分割,名字和姓氏被 :
分割 ->
"Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill"
我想要return一个字符串,它把所有的名字都按大写字母排序,并根据姓氏和具有相同姓氏的字母顺序排序,然后再次排序(二次排序)具有相同姓氏的人的名字。 (我也故意将所有内容更改为大写)。
和 return 排序名称的字符串,因此对于上面的示例,它应该 return:
"(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)
而不是 the反过来。
在下面的解决方案中,我 运行 它得到了一个错误:
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
结果是假的
如果您正在使用 Java 流,您可以像这样使用 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)
我还建议使用对象而不是字符串来存储您的信息,使用它不是一个好习惯。
一个可能的解决方案如下:
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);
}
}
}
您可以使用比较器链先按一个值排序,然后再按另一个值排序:
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?
我正在尝试一种方法,当给定一串名字(名字和姓氏)时,名字被 ;
分割,名字和姓氏被 :
分割 ->
"Fred:Corwill;Wilfred:Corwill;Barney:Tornbull;Betty:Tornbull;Bjon:Tornbull;Raphael:Corwill;Alfred:Corwill"
我想要return一个字符串,它把所有的名字都按大写字母排序,并根据姓氏和具有相同姓氏的字母顺序排序,然后再次排序(二次排序)具有相同姓氏的人的名字。 (我也故意将所有内容更改为大写)。
和 return 排序名称的字符串,因此对于上面的示例,它应该 return:
"(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)
而不是 the反过来。
在下面的解决方案中,我 运行 它得到了一个错误:
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
结果是假的
如果您正在使用 Java 流,您可以像这样使用 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)
我还建议使用对象而不是字符串来存储您的信息,使用它不是一个好习惯。
一个可能的解决方案如下:
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);
}
}
}
您可以使用比较器链先按一个值排序,然后再按另一个值排序:
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?