简体   繁体   English

比较列表中字符串的日期

[英]Compare dates from a String in list

I'm having a problem continuing.我在继续时遇到问题。 I have a list and in each position contains a String (within the phrase there is at the end a date)我有一个列表,在每个 position 中都包含一个字符串(在该短语的末尾有一个日期)

Example:例子:

I am new here 20/8/2019 

I want to sort the list this way: In position zero I want the phrase containing the oldest date and the following positions the date will be more recent.我想以这种方式对列表进行排序:在 position 零中,我想要包含最旧日期和以下位置的短语,日期将更新。

I tried to use SimpleDateFormat and Date, but I didn't know how to do it.我尝试使用 SimpleDateFormat 和 Date,但我不知道该怎么做。

String variable, variable2, c;
int d = 0;
for(int i = 0; i < lista.size(); i++) {
    for(int j = 1; j <lista.size(); j++) {
        variable = lista.get(i);
        variable2 = lista.get(j);
        c = compareDates(variable, variable2);
        lista.add(d,c);
        d++;
    }
}

private static Date compareDates(String variable, String variable2) throws ParseException {
    SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy");
    String var = formateador.format(variable);
    String var2 = formateador.format(variable2);
    if (var.before(var2)) {
        return var;
    } else {
        if (var2.before(var1)) {

        } else {

        }
        return null;
    }
}

Exception in thread "main" java.lang.Error: Unresolved compilation problem: Type mismatch: cannot convert from Date to String线程“主”java.lang.Error 中的异常:未解决的编译问题:类型不匹配:无法从日期转换为字符串

at Ejercicio.ClaseMain.leerDes(ClaseMain.java:124)

Line 124: c = compareDates(variable, variable2);第 124 行:c = compareDates(variable, variable2);

Visual example: Each position in the list has a phrase with a date:视觉示例:列表中的每个 position 都有一个带有日期的短语:

在此处输入图像描述

The thing is, I read a.txt file, where there are several lines.问题是,我读了一个 .txt 文件,其中有几行。 Contents of the file:文件内容:

Sevilla reserves himself to Apoel and wins without brilliance;塞维利亚将自己保留给Apoel,并没有光彩夺冠; sport Julen Lopetegui revolutionized the eleven with the aim of giving rest to the regulars, which did not prevent his team from adding his second triumph of the competition sportyou 10/10/2019体育 Julen Lopetegui 彻底改变了 11 人,旨在将 rest 给予常客,这并没有阻止他的团队在比赛中获得第二次胜利 2019 年 10 月 10 日

A painting by Banksy of the British Parliament occupied by chimpanzees, sold >for 11 million euros culture An oil of artist Banksy representing the British House of Commons full of chimpanzees was topped on Thursday at an auction in London for 9.8 million pounds (11 million euros) 10/2019班克斯的一幅英国议会被黑猩猩占领的画作,以 1100 万欧元成交) 10/2019

I use a while to read the file line and save each line at each position in the list, and I want to sort the list.我用一段时间来读取文件行并将每一行保存在列表中的每个 position 处,我想对列表进行排序。 Old date ---> recent date.旧日期 ---> 最近日期。

Please don't use the legacy Date library, instead use java.time API, so if you are using Java 8 your solution can be:请不要使用旧的日期库,而是使用java.time API,所以如果您使用的是 Java 8,您的解决方案可以是:

String[] strs = {"20/10/2019", "5/2/2019", "12/12/2019",
        "1/8/2019", "25/12/2019", "2/1/2019", "6/9/2019"};
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/uuuu");
List<LocalDate> collect = Stream.of(strs)
        .map(s -> LocalDate.parse(s, formatter))  // convert your strings to dates
        .sorted() // sort the dates
        .collect(Collectors.toList()); // collect the result in a collection

Output Output

[2019-01-02, 2019-02-05, 2019-08-01, 2019-09-06, 2019-10-20, 2019-12-12, 2019-12-25]

Considering all the strings in List are of same format and having date at fourth index after split, like below考虑到List中的所有字符串格式相同,并且在拆分后的第四个索引处具有date ,如下所示

List<String> list = new ArrayList<>();
list.add("I am new here 20/11/2019 ");
list.add("I am Deadpool here 20/7/2019 ");
list.add("I am IronMan here 20/6/2019 ");

Now use comparator to sort the List based on LocalDate现在使用比较器根据LocalDateList进行排序

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/M/yyyy");
list.sort(Comparator.comparing(str->LocalDate.parse(str.split(" ")[4],formatter)));

    System.out.println(list);  //I am IronMan here 20/6/2019 , I am Deadpool here 20/7/2019 , I am new here 20/11/2019 ]

My solution would be:我的解决方案是:

    List<String> lista = List.of(
            "Sevilla reserves himself to Apoel … sportyou 10/10/2019",
            "I am new here 20/8/2019",
            "A painting by Banksy … 19/10/2019");
    List<String> sortedList = lista.stream()
            .map(s -> new Object() {
                String theString = s;
                LocalDate date = extractDate(s);
            })
            .sorted(Comparator.comparing(obj -> obj.date))
            .map(obj -> obj.theString)
            .collect(Collectors.toList());
    sortedList.forEach(System.out::println);

Output from this is: Output 这是:

 I am new here 20/8/2019 Sevilla reserves himself to Apoel … sportyou 10/10/2019 A painting by Banksy … 19/10/2019

The extractDate method that I am using is:我使用的extractDate方法是:

private static Pattern datePattern = Pattern.compile("\\d{1,2}/\\d{1,2}/\\d{4}$");
private static DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("d/M/u");

private static LocalDate extractDate(String fullString) {
    Matcher m = datePattern.matcher(fullString);
    if (m.find()) {
        String dateString = m.group();
        return LocalDate.parse(dateString, dateFormatter);
    } else {
        throw new IllegalArgumentException("String doesn’t end with a date: " + fullString);
    }
}

For efficient sorting of the strings — it only matters if there are many — I am extracting the trailing date and parsing it only once for each string (not for every comparison).为了对字符串进行有效排序——只有在有很多字符串时才重要——我提取了尾随日期并为每个字符串只解析一次(而不是每次比较)。 I am parsing into LocalDate and use these for sorting.我正在解析LocalDate并使用它们进行排序。 In order to get the original strings out after sorting I have put both the String and the LocalDate into an object and then sort these objects.为了在排序后取出原始字符串,我将StringLocalDate都放入 object 中,然后对这些对象进行排序。 It may surprise some that I can use an anonymous subclass of Object in this way, but it works nicely.我可以以这种方式使用Object的匿名子类,这可能会让一些人感到惊讶,但它工作得很好。

I recommend you don't use SimpleDateFormat and Date .我建议您不要使用SimpleDateFormatDate Those classes are poorly designed and long outdated, the former in particular notoriously troublesome.这些类设计不佳且早已过时,尤其是前者,尤其是出了名的麻烦。 Instead I am using LocalDate and DateTimeFormatter , both from java.time, the modern Java date and time API.相反,我使用LocalDateDateTimeFormatter ,两者都来自 java.time,现代 Java 日期和时间 API。

Java has nice sorting facilities built-in. Java 内置了不错的分拣设施。 If writing your own sorting algorithm was for an exercise, that's a good exercise.如果编写自己的排序算法是为了练习,那是一个很好的练习。 Frankly you still had a way to go before your sorting would work.坦率地说,在你的排序工作之前,你仍然有办法 go 。 You may want to read up on sorting algorithms, there's a lot written, also on the WWW.您可能想阅读排序算法,在 WWW 上也有很多文章。 For production code you should rely on a library method.对于生产代码,您应该依赖库方法。

Link: Oracle tutorial: Date Time explaining how to use java.time.链接: Oracle 教程:日期时间解释如何使用 java.time。

The dates like "20/8/2019" are not matching the pattern "dd/MM/yyyy".像“20/8/2019”这样的日期与“dd/MM/yyyy”模式不匹配。 The correct format should be like "20/08/2019".正确的格式应该是“20/08/2019”。 And the shortest solution for sorting is排序的最短解决方案是

list.sort(Comparator.comparing(
    source -> LocalDate.parse(source, DateTimeFormatter.ofPattern("dd/MM/yyyy"))));

The error is happening because at compareDates the method return type is Date while the returns are String .发生错误是因为在compareDates方法返回类型是Date而返回是String

Now coming to the solution, if the intent is to just get the sorted dates extracted from the phrases this should work.现在来到解决方案,如果目的只是从短语中提取排序日期,这应该可行。 But looking at the code in OP I sense you're trying to bubble sort the list of phrases sorted by dates which can also be achieved following the same lines.但是查看 OP 中的代码,我感觉您正在尝试对按日期排序的短语列表进行冒泡排序,这也可以按照相同的方式实现。

The important part is extraction of the date via Regex .重要的部分是通过Regex提取日期。

Code:代码:

List<LocalDate> ld = new ArrayList<LocalDate>();
for(int i = 0; i < lista.size(); i++){
  ld.add(getDateFromString(lista.get(i)));
}
//sorting the list of dates extracted
ld = ld.stream().sorted().collect(Collectors.toCollection(ArrayList::new));

private static LocalDate getDateFromString(String str){
  LocalDate d;
  //looks for pattern dd/mm/yyyy in the passed string
  Matcher m = Pattern.compile("(\\d{1,2}/\\d{1,2}/\\d{4})").matcher(str);
  if(m.find()) {
   String match = m.group(1);
   d = LocalDate.parse(match, DateTimeFormatter.ofPattern("d/MM/yyyy"));
  }
  return d;
}

Note: This takes the assumption that every phrase will have one date string in the form of dd/mm/yyyy注意:这里假设每个短语都有一个日期字符串,格式为dd/mm/yyyy

Simply, if you don't know the format of the date strings, its not possible to convert the strings to dates.简单地说,如果您不知道日期字符串的格式,就不可能将字符串转换为日期。 Is "10/11/12" the 11 of October or the 10th of November of year '12 or is it the 12 of November of year '10? “10/11/12”是 10 月 11 日还是 12 年 11 月 10 日,还是 10 年 11 月 12 日? See How to convert String to Date without knowing the format?请参阅如何在不知道格式的情况下将字符串转换为日期? . .

In your text example, the last date is simply "10/2019" and you used "20/8/2019" as another example so it seems you have a mix of possible formats.在您的文本示例中,最后一个日期只是“10/2019”,而您使用“20/8/2019”作为另一个示例,因此您似乎有多种可能的格式。 If you could limit the possibilities, it might be possible to find the best match.如果您可以限制可能性,则可能会找到最佳匹配。

If you can extract that date using regex as a sequence of numbers and forward slashes at the end of the text (see answer from ambianBeing ), then you could try to parse this string using the possible formats from most strict to most relaxed, trapping the 'DateTimeParseException' exceptions and stopping at the first successful parse.如果您可以使用正则表达式提取该日期作为文本末尾的数字序列和正斜杠(请参阅ambianBeing的答案),那么您可以尝试使用从最严格到最宽松的可能格式解析此字符串,捕获'DateTimeParseException' 异常并在第一次成功解析时停止。 If nothing succeeds, flag it so you can determine what to fix - either the text, add a new format or a better regex expression.如果没有成功,请标记它,以便您确定要修复的内容 - 文本、添加新格式或更好的正则表达式。

Using the examples above, you could start with format patterns使用上面的示例,您可以从格式模式开始

  • dd/MM/yyyy
  • dd/M/yyyy
  • MM/yyyy

If everything fails, use a null date to flag the entry.如果一切都失败了,请使用 null 日期来标记条目。

If you put this in a method that returns the date, you can then use the stream solution to sort the list as suggested by several others.如果将其放入返回日期的方法中,则可以使用 stream 解决方案按照其他几个人的建议对列表进行排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM