排序某种格式的特定字符串

时间:2013-10-30 00:08:06

标签: java algorithm

我试图在逻辑上对此进行排序 假设我有一个包含以下元素的字符串列表

String[] myList = {"Spring 2013", "Fall 2009", "Fall 2010", "Spring 2012"};

我想知道如何对结果集进行排序 2009年秋季,2010年秋季,2012年春季,2013年春季

感谢您的帮助,谢谢!

4 个答案:

答案 0 :(得分:2)

假设您无法重新格式化字符串,您可以编写实现该逻辑的自定义比较器。你的Comparator会调用split来分开学期和年份。然后它可以比较第一年,然后是自定义月/学期逻辑。

您可以使用列表和自定义比较器调用Collections.sort或Arrays.sort。

答案 1 :(得分:1)

请注意,“春天”和“秋季”等季节名称比年份“重要”,

此外,季节不是按字母顺序排序,而是按冬季,春季,夏季,秋季(我假设?)。

因此,如果您将“Fall 2010”转换为“20104”和“Spring 2013”​​转换为“20132”,那么您可以将它们排序为数字。

答案 2 :(得分:0)

在这种情况下,所需的顺序是自然(按字母顺序)顺序,因此您可以使用Arrays.sort(Object\[\])方法。如果所需订单与自然订单不符,您可以实施Comparator并使用Arrays.sort(String\[\], Comparator<String>)方法。

Comparator实施的一个示例(只是为了说明它是如何工作的):

public class SemesterComparator implements Comparator<String> {

    private static final List<String> SEASONS = Arrays.asList("Spring", "Summer", "Fall", "Winter");

    @Override
    public int compare(String one, String two) {
        String[] partsOne = one.split(" ");
        String[] partsTwo = two.split(" ");
        if (partsOne.length != 2 || partsTwo.length != 2) {
            throw new IllegalArgumentException();
        }
        if (!SEASONS.contains(partsOne[0]) || !SEASONS.contains(partsTwo[0])) {
            throw new IllegalArgumentException();
        }

        // compare years
        int comparison = partsOne[1].compareTo(partsTwo[1]);
        if (comparison == 0) {
            // if years are equal: compare season
            comparison = SEASONS.indexOf(partsOne[0]).compareTo(SEASONS.indexOf(partsTwo[0]));
        }
        return comparison;
    }
}

但正如评论中已经提到的那样,最好将值存储在可以更好排序的格式或类中。

答案 3 :(得分:0)

以下是Comparator#compare函数的外观:

int compare(String o1, String o2) {
   // null values always prioritized
   if (o1 == o2) return 0;
   if (o1 == null) return -1;
   if (o2 == null) return 1;

   String[] parts1 = o1.split(' '); // e.g. ["Fall", "2012"]
   String[] parts2 = o2.split(' ');

   // invalid data, just throw some nonsense ordering out
   if (parts1.length != 2 || parts2.length != 2) {
     return parts2.length - parts1.length;
   }

   // have winner, 4 digit years can be compared lexicographical
   var yearCompare = parts[1].compareTo(parts[2]);
   if (yearCompare != 0) {
     return yearCompare;
   }

   // map term names to orderable values
   String[] termWeights = { "Spring", "Summer", "Fall", "Winter" };
   var term1 = termWeights.indexOf(parts1[0]);
   var term2 = termWeights.indexOf(parts2[0]);

   // invalid terms prioritized
   if (term1 == term2) return 0;
   if (term1 == -1) return -1;
   if (term2 == -1) return 1;

   return term2 - term1;
}

当然,我根本没有测试过这个。 YMMV:)

这是另一种替代方法(基于评论):

// swap "TermName Year" to "Year TermName"
String prioritizeYear (String i) {
   return i.replaceFirst("^(\\w+)\\s+(\\d+)", "$2_$1");
}

// convert "TermName" to "TermValue"
String weightTerm (String i) {
   return i.replace("Spring", "1")
           .replace("Summer", "2")
           .replace("Fall", "3")
           .replace("Winter", "4");
}

int compare(String o1, String o2) {
   // null values always prioritized
   if (o1 == o2) return 0;
   if (o1 == null) return -1;
   if (o2 == null) return 1;

   String n1 = weightTerm(prioritizeYear(o1));
   String n2 = weightTerm(prioritizeYear(o2));

   return n1.compareTo(n2);
}

再次,YMMV。