【问题标题】:How can I add the missing time using LocalTime in ObservableList?如何在 ObservableList 中使用 LocalTime 添加丢失的时间?
【发布时间】:2018-06-28 06:38:06
【问题描述】:

我正在尝试创建一个日程安排,我只能获取输入的时间和日程名称。

我想把日程安排在List,但如果没有其他日程安排,如果没有其他早期时间,列表应该从6:00 AM开始添加一个新的空日程安排。

我有ObservableList<DataClass>,它包含LocalTime 和一些String

示例 1: 假设列表包含 3 个项目:

[04:00 AM] [Some String]
[06:30 AM] [Some String]
[05:00 PM] [Some String]

我想将列表中缺少的时间从4:00 AM 添加到5:00 PM,所以列表将是:

[04:00 AM] [Some String]
[05:00 AM] [Some String]
[06:30 AM] [Some String]
[07:00 AM] [Some String]
[08:00 AM] [Some String]
[09:00 AM] [Some String]
[10:00 AM] [Some String]
[11:00 AM] [Some String]
[12:00 PM] [Some String]
[01:00 PM] [Some String]
[02:00 PM] [Some String]
[03:00 PM] [Some String]
[04:00 PM] [Some String]
[05:00 PM] [Some String]

示例 2: 假设列表包含 2 个项目:

[08:30 AM] [Some String]
[02:00 PM] [Some String]

我想将列表中缺少的时间从6:00 AM添加到5:00 PM,所以列表将是:

[06:00 AM] [Some String]
[07:00 AM] [Some String]
[08:00 AM] [Some String]
[09:00 AM] [Some String]
[10:00 AM] [Some String]
[11:00 AM] [Some String]
[12:00 PM] [Some String]
[01:00 PM] [Some String]
[02:00 PM] [Some String]
[03:00 PM] [Some String]
[04:00 PM] [Some String]
[05:00 PM] [Some String]

示例 3: 假设列表包含 1 个项目:

[08:00 PM] [Some String]

我想将列表中缺少的时间从6:00 AM添加到8:00 PM,这样列表就可以了。

[06:00 AM] [Some String]
[07:00 AM] [Some String]
[08:00 AM] [Some String]
[09:00 AM] [Some String]
[10:00 AM] [Some String]
[11:00 AM] [Some String]
[12:00 PM] [Some String]
[01:00 PM] [Some String]
[02:00 PM] [Some String]
[03:00 PM] [Some String]
[04:00 PM] [Some String]
[05:00 PM] [Some String]
[06:00 PM] [Some String]
[07:00 PM] [Some String]
[08:00 PM] [Some String]

如果没有其他更早的时间,时间应该从06:00 AM开始,否则时间将从那个早的时间开始。

如果没有其他时间,时间应该在5:00 PM结束,否则时间将在那个特定时间结束,我只想添加HOUR,比如increment小时所以不应该有6:30 , 5:30 除非是手动输入的。

我正在考虑以下逻辑,但由于想法被锁定,我无法继续。

  1. 根据从上午到下午的时间对列表进行排序以获得第一次

  2. 检查第一个数据的时间是否等于或小于上午 6:00
    如果为真,则从那个时间开始并继续添加缺失的 直到下午 5:00 或最后一次到达的时间。
    如果为假,则 从早上 6:00 开始并继续添加缺失的时间直到 5:00 下午或最后一次到达。

下面的代码是我目前所拥有的,令人费解。

private void fillTheList(){
        ObservableList<DataClass> data = FXCollections.observableArrayList();
        Comparator<DataClass> comparator = Comparator.comparing(DataClass::getLocalTime);

        data.add(new DataClass(convertTime("05:00 PM"), "Sample Content"));
        data.add(new DataClass(convertTime("06:30 AM"), "Sample Content"));

        FXCollections.sort(data,comparator); //Sort the list from AM to PM

        for (DataClass list : data){
            if(list.getLocalTime().isBefore(LocalTime.of(6,0))){
                //The time is less than 6:00 AM then it should start here and Add the missing time but I don't know what to do next...
            }else{
                //the time is not less than 6:00 AM... I don't know what to do next..
            }
        }
        FXCollections.sort(data,comparator); //Sort the list from AM to PM again
}

private LocalTime convertTime(String timeString){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a");
        return LocalTime.parse(timeString, formatter);
}

PS:我实际上不确定我要问什么,所以如有必要,请随时提出修改建议。

更新:DataClass.class

public class DataClass {

    private LocalTime localTime;
    private String content;

    public DataClass(LocalTime localTime, String content){
        this.localTime = localTime;
        this.content = content;
    }

    public LocalTime getLocalTime(){
        return localTime;
    }

    public String getContent(){
        return content;
    }
}

【问题讨论】:

  • 通过用.... to 替换行,您已经消除了我们需要了解您要完成的任务的关键信息。生成“缺失”时间的具体规则是什么?什么是间隔?它是恒定的吗?这个问题非常不清楚。
  • PS: I'm not actually sure what I'm going to ask so feel free to suggest an edit if necessary. - 如果您不知道自己需要什么,我们很难知道您需要什么。
  • @Jai - 我知道我想要实现的目标,但我不知道如何问它。
  • 你能给DataClass类吗?尝试一下会有所帮助
  • @azro - 更新

标签: java javafx localtime observablelist


【解决方案1】:

你自己在路上很好。此外,azro 是正确的,您需要通过与数据中已有的最小和最大时间进行比较来找到要考虑插入的最小和最大小时。 Jai 是正确的,您应该在插入时间之前检查时间是否已经在列表中,并且流对此目的很方便。我的版本使用int 来迭代几个小时,但所有其他版本都是正确的,LocalTime 也可以工作。

    int minHour = 6;
    int maxHour = 17;
    if (! data.isEmpty()) {
        // adjust min and max from list contents
        int minExisintgHour = data.get(0).getLocalTime().getHour();
        if (minExisintgHour < minHour) {
            // if the list already contained 4:00 or 4:30,
            // we only need to add hours from 5, so add 1
            minHour = minExisintgHour + 1;
        }
        int maxExisintgHour = data.get(data.size() - 1).getLocalTime().getHour();
        if (maxExisintgHour > maxHour) {
            maxHour = maxExisintgHour;
        }
    }
    for (int hour = minHour; hour <= maxHour; hour++) {
        LocalTime time = LocalTime.of(hour, 0);
        boolean alreadyInData = data.stream().anyMatch(d -> d.getLocalTime().equals(time));
        if (! alreadyInData) {
            data.add(new DataClass(time, "Added beacuse time was missing"));
        }
    }

我假设您在上述代码之前和之后对列表进行排序,如问题所示。如果您对 min 和 max 进行线性遍历,则可以省略之前的排序(一些流也可以这样做)。

示例结果列表:

[06:00 AM] [Added beacuse time was missing]
[06:30 AM] [Sample Content]
[07:00 AM] [Added beacuse time was missing]
[08:00 AM] [Added beacuse time was missing]
[09:00 AM] [Added beacuse time was missing]
[10:00 AM] [Added beacuse time was missing]
[11:00 AM] [Added beacuse time was missing]
[12:00 PM] [Added beacuse time was missing]
[01:00 PM] [Added beacuse time was missing]
[02:00 PM] [Added beacuse time was missing]
[03:00 PM] [Added beacuse time was missing]
[04:00 PM] [Added beacuse time was missing]
[05:00 PM] [Sample Content]

【讨论】:

    【解决方案2】:

    您必须按照以下步骤操作

    1. 获取start的值,它将是06AM或列表的第一个值,取决于哪个是第一个

    2. 获取end的值,它只是第二个值

    3. 清除列表以删除开始和结束值
    4. 遍历 2 之间的所有日期,每次递增 1 小时
    5. 结束条件是i.isBefore(end.plusHours(1)) 而不是i.isBefore(end),因为您需要包含end 元素
    6. 排序和打印
    ObservableList<DataClass> data = FXCollections.observableArrayList();
    Comparator<DataClass> comparator = Comparator.comparing(DataClass::getLocalTime);
    
    data.add(new DataClass(convertTime("05:00 PM"), "Sample Content"));
    data.add(new DataClass(convertTime("06:30 AM"), "Sample Content"));
    
    FXCollections.sort(data,comparator); //Sort the list from AM to PM
    // 1. & 2.
    LocalTime begin = LocalTime.of(6,0);
    if(data.get(0).getLocalTime().isBefore(begin)){
       begin = data.get(0).getLocalTime();
    }
    
    LocalTime end = LocalTime.of(17,0);
    if(end.isBefore(data.get(data.size()-1).getLocalTime())){
        end = data.get(data.size()-1).getLocalTime();
    }
    
    // 3.
    data.clear();
    // 4. & 5.
    for(LocalTime i = begin.withMinute(0); !i.isAfter(end); i = i.plusHours(1)){
       data.add(new DataClass(i, "Sample Content"));        
    }
    
    // 6. 
    FXCollections.sort(data,comparator); //Sort the list from AM to PM again
    System.out.println(data);
    //  [06:00, 07:00, 08:00, 09:00, 10:00, 11:00, 12:00, 13:00, 14:00, 15:00, 16:00, 17:00]
    

    【讨论】:

    • 谢谢,但是有个小问题,比如4:30 AM,不是早点开始,早点是remove,总是从6:00 AM开始。此外,带分钟的时间已删除示例6:30 AM。无论如何,谢谢,非常接近......我正在寻找您的代码中缺少的内容,但我希望它能够修复。
    • @KrixMuxDeadpool 我已经编辑了开始/结束计算和循环,它应该可以工作
    • 我以为你只想要时间:00,你能举个不工作的例子吗?编辑您的帖子
    • @KrixMuxDeadpool juste remove .withMinutes(0) in the loop condition,然后告诉我
    • @KrixMuxDeadpool 你能和 :30 分享一个例子吗?删除 .withMinute(0) 它对我有用,如果输入 04:30AM,您将在 05:30、06:30、...
    【解决方案3】:

    不完全确定您需要什么,但这可能是您需要的:

    ObservableList<DataClass> data = FXCollections.observableArrayList();
    
    // Need to specify the period that you want the entries to be filled
    private void fill(LocalTime from, LocalTime to) {
        // Keep adding new entries until we have reached the end
        while (!from.isAfter(to)) {
            // We need a final variable for stream()
            final LocalTime temp = from;
    
            // If data does not contain any time that is equivalent to this time
            if (data.stream().noneMatch(d -> temp.equals(d.getLocalTime()))) {
                data.add(new DataClass(temp, "Hello World"));
            }
    
            // Increment the time by an hour, and wait for next loop cycle
            from = from.plusHours(1);
        }
    }
    

    除非您想以排序方式显示数据,否则排序没有任何意义。

    更新

    此实现不会阻止您传入带有分钟(或秒)值的 fromto

    如果您需要它以纯小时为单位,则可以将其更改为:

    ObservableList<DataClass> data = FXCollections.observableArrayList();
    
    // Need to specify the period that you want the entries to be filled
    private void fill(int fromHour, int toHour) {
        LocalTime from = LocalTime.of(fromHour, 0);
        LocalTime to = LocalTime.of(toHour, 0);
    
        // Keep adding new entries until we have reached the end
        while (!from.isAfter(to)) {
            // We need a final variable for stream()
            final LocalTime temp = from;
    
            // If data does not contain any time that is equivalent to this time
            if (data.stream().noneMatch(d -> temp.equals(d.getLocalTime()))) {
                data.add(new DataClass(temp, "Hello World"));
            }
    
            // Increment the time by an hour, and wait for next loop cycle
            from = from.plusHours(1);
        }
    }
    

    这将强制两个边界值只有小时值。

    【讨论】:

    • 没有解释的答案不是一个
    • 未添加数据。 . .
    • @KrixMuxDeadpool 这取决于fromto(当然也取决于列表中已有的数据)。
    • from.isBefore(to) 更改为 !from.isAfter(to) 以包括结束时间。另外,请注意,这期望两个时间值都是整小时值。
    • 假设凝视时间是5:30 AM,那么一切都会有30 minutes
    【解决方案4】:

    如下进行

    1. 对列表进行排序
    2. 设置可能需要插入的时间(从插入范围的下限开始)
    3. 找到第一个元素的索引,时间>=要插入的时间
    4. 如果元素的时间与要插入的时间不匹配,则在该索引处插入一个新元素
    5. 如果您还没有离开插入范围,请修改要插入的时间并继续 3.
    ObservableList<DataClass> data = ...
    LocalTime lowerBound = LocalTime.of(6, 0); // or some other input
    LocalTime upperBound = LocalTime.of(12 + 5, 0); // or some other input
    
    
    Comparator<DataClass> comparator = Comparator.comparing(DataClass::getLocalTime);
    FXCollections.sort(data, comparator);
    
    int size = data.size();
    int index = 0;
    
    while (!lowerBound.isAfter(upperBound)) {
        // find inserting index
        while (index < size && data.get(index).getLocalTime().isBefore(lowerBound)) {
            index++;
        }
        // insert, if not already in list
        if (index >= size || !data.get(index).getLocalTime().equals(lowerBound)) {
            data.add(index, new DataClass(lowerBound, "Inserted"));
            size++;
        }
        lowerBound = lowerBound.plusHours(1);
        index++;
    }
    

    请注意,对于列表中较小的步骤和较大数量的元素,代码的性能是次优的,因为添加到列表的中间会在O(n) 中运行,因此产生的复杂度将是O(i + i*n + n*log(n)) 其中@987654324 @ 是插入次数,n 是列表的初始大小。

    为了改善这一点,您可以将所有新元素添加到列表的末尾,然后使用一次来自 mergesort 的合并步骤,这将导致运行时 O(i+n*log(n))

    final int size = data.size();
    int index = 0;
    
    while (!lowerBound.isAfter(upperBound)) {
        // find inserting index
        while (index < size && data.get(index).getLocalTime().isBefore(lowerBound)) {
            index++;
        }
        // insert, if not already in list
        if (index >= size || !data.get(index).getLocalTime().equals(lowerBound)) {
            data.add(new DataClass(lowerBound, "Inserted"));
        } else {
            index++;
        }
        lowerBound = lowerBound.plusHours(1);
    }
    
    // merge
    DataClass[] merged = new DataClass[data.size()];
    int insertionIndex = 0;
    int index1 = 0;
    int index2 = size;
    while (index1 < size && index2 < merged.length) {
        DataClass v1 = data.get(index1);
        DataClass v2 = data.get(index2);
        if (v2.getLocalTime().isBefore(v1.getLocalTime())) {
            merged[insertionIndex] = v2;
            index2++;
        } else {
            merged[insertionIndex] = v1;
            index1++;
        }
        insertionIndex++;
    }
    
    // copy remaining
    while (index1 < size) {
        merged[insertionIndex++] = data.get(index1++);
    }
    while (index2 < merged.length) {
        merged[insertionIndex++] = data.get(index2++);
    }
    data.setAll(merged);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-21
      • 2012-01-29
      • 2021-03-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-23
      • 2020-04-03
      • 2018-04-23
      相关资源
      最近更新 更多