Сравните даты из строки в списке - PullRequest
4 голосов
/ 09 ноября 2019

У меня проблема с продолжением. У меня есть список, и в каждой позиции содержится строка (внутри фразы есть в конце дата)

Пример:

I am new here 20/8/2019 

Я хочу отсортировать список следующим образом: Внулевая позиция Я хочу фразу, содержащую самую старую дату, а в следующих позициях дата будет более новой.

Я пытался использовать 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;
    }
}

Исключение в потоке "main" java.lang.Error: Неразрешенная проблема компиляции:Несоответствие типов: невозможно преобразовать дату в строку

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

Строка 124: c = compareDates (variable, variable2);

Визуальный пример: каждая позиция в спискеимеет фразу с датой:

enter image description here

Дело в том, что я читаю файл .txt, где есть несколько строк. Содержимое файла:

Севилья оставляет себя за Апоэля и побеждает без блеска;спорт Julen Lopetegui произвел революцию в одиннадцати с целью дать отдых постоянным клиентам, что не помешало его команде добавить свой второй триумф в соревновании sportyou 10/10/2019

Картина Бэнкси из британского парламентазанятые шимпанзе, проданные> за 11 миллионов евро культуры Нефть художника Бэнкси, представляющего британскую Палату общин, полную шимпанзе, была подорожена в четверг на аукционе в Лондоне за 9,8 миллиона фунтов (11 миллионов евро) 10/2019

Я использую некоторое время, чтобы прочитать строку файла и сохранить каждую строку в каждой позиции в списке, и я хочу отсортировать список. Старая дата ---> недавняя дата.

Ответы [ 6 ]

2 голосов
/ 10 ноября 2019

Мое решение было бы:

    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);

Выходные данные:

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

Используемый мной метод 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);
    }
}

Для эффективной сортировки строк - это имеет значение только если их много - я извлекаю конечную дату и анализирую ее только один раз для каждой строки (не для каждого сравнения). Я анализирую LocalDate и использую их для сортировки. Чтобы получить исходные строки после сортировки, я поместил String и LocalDate в объект, а затем отсортировал эти объекты. Некоторых может удивить то, что я могу использовать анонимный подкласс Object таким образом, но он прекрасно работает.

Я рекомендую не использовать SimpleDateFormat и Date. Эти классы плохо спроектированы и давно устарели, а первые особенно печально известны. Вместо этого я использую LocalDate и DateTimeFormatter, оба из java.time, современный API даты и времени Java.

Java имеет встроенные удобные средства сортировки. Если написание собственного алгоритма сортировки было для упражнения, это хорошее упражнение. Честно говоря, у вас еще был путь до того, как ваша сортировка сработает. Вы можете прочитать об алгоритмах сортировки, там много написано, в том числе и в WWW. Для производственного кода вы должны полагаться на библиотечный метод.

Ссылка: Обучающее руководство по Oracle: Дата и время , объясняющее, как использовать java.time.

2 голосов
/ 09 ноября 2019

Учитывая, что все строки в 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 ");

Теперь используйте компаратор для сортировки List на основе LocalDate

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 ]
2 голосов
/ 09 ноября 2019

Пожалуйста, не используйте устаревшую библиотеку Date, вместо этого используйте 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

[2019-01-02, 2019-02-05, 2019-08-01, 2019-09-06, 2019-10-20, 2019-12-12, 2019-12-25]
1 голос
/ 09 ноября 2019

Проще говоря, если вы не знаете формат строк даты, невозможно преобразовать строки в даты. Является ли "10/11/12" 11 октября или 10 ноября 12 года или 12 ноября 10 года? См. Как преобразовать строку в дату, не зная формат? .

В вашем текстовом примере последняя дата - просто "10/2019", и вы использовали "20/8/2019" в качестве другого примера, поэтому, похоже, у вас есть смесь возможных форматов. Если бы вы могли ограничить возможности, можно было бы найти наилучшее совпадение.

Если вы можете извлечь эту дату, используя регулярное выражение в виде последовательности чисел и косых черт в конце текста (см. Ответ из ambianBeing ), тогда вы можете попытаться проанализировать эту строку, используя возможные форматы от самых строгих до наиболее расслабленных, перехватывая исключения DateTimeParseException и останавливаясь при первом успешном анализе. Если ничего не получится, пометьте его, чтобы вы могли определить, что исправить - текст, добавить новый формат или лучшее выражение регулярного выражения.

Используя приведенные выше примеры, вы можете начать с шаблонов форматов

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

Если все не удается, используйте нулевую дату, чтобы отметить запись.

Если вы поместите это в метод, который возвращает дату, вы можете затем использовать потоковое решение для сортировки списка, как предложено несколькими другими.

1 голос
/ 09 ноября 2019

Ошибка возникает из-за того, что при compareDates тип возвращаемого значения метода Date, а при возврате String.

Теперь перейдем к решению, если целью является получение только отсортированных датизвлеченные из фраз это должно работать. Но глядя на код в OP, я чувствую, что вы пытаетесь отсортировать по фразам список фраз, отсортированных по датам, что также может быть достигнуто по тем же строкам.

Важной частью является извлечение даты через * 1008. *.

Код:

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;
}

Примечание: Предполагается, что каждая фраза будет иметь одну строку даты в виде dd/mm/yyyy

1 голос
/ 09 ноября 2019

Даты типа «20/8/2019» не соответствуют шаблону «дд / мм / гггг». Правильный формат должен быть как «20/08/2019». И самое короткое решение для сортировки -

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