RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1508408
Accepted
SergeyMih
SergeyMih
Asked:2023-03-27 14:31:28 +0000 UTC2023-03-27 14:31:28 +0000 UTC 2023-03-27 14:31:28 +0000 UTC

14天内将服务列表分组

  • 772

有一个服务列表,例如:

List<Item>  list = new ArrayList<>();
list.add(new Item(123456789, 01.04.2023));
list.add(new Item(123456789, 14.04.2023));
list.add(new Item(123456789, 21.04.2023));
list.add(new Item(123456789, 30.04.2023));

格式中的日期LocalDate,但为了清楚起见,这样表示。

有必要将服务列表分组,以便每个组在 14 天内都有服务。例如,对于上面的示例,将有两组:

第一个日期为 04/01/2023 和 04/14/2023 第二个日期为 04/21/2023 和 04/30/2023

我喜欢这样:

list.sort(Comparator.comparing(Item::getDate_in));

Map<Integer, List<Item>> groups = list.stream()
        .collect(Collectors.groupingBy(i ->
                (int) ChronoUnit.DAYS.between(list.get(0).getDate_in(), i.getDate_in()) / 14));

for (Map.Entry<Integer, List<Item>> entry1 : groups.entrySet()) {
    System.out.println(entry1.getKey());
    for (Item Item : entry1.getValue()) {
        System.out.println(Item + " \n");
    }
}

但结果是三个小组而不是两个。你能告诉我分组的最佳方法吗?

Map<Boolean, List<Item>>在问题https://ru.stackoverflow.com/questions/1507202/Separate-elements-by-conditions/1507257?noredirect=1#comment2704072_1507257中使用as是不合适的,因为此解决方案是将列表分为两组,并且可能会有三个小组。例如像这样:

List<Item>  list = new ArrayList<>();
list.add(new Item(123456789, 01.04.2023));
list.add(new Item(123456789, 14.04.2023));
list.add(new Item(123456789, 15.04.2023));
list.add(new Item(123456789, 30.04.2023));

应该已经有三个组了。

java
  • 2 2 个回答
  • 45 Views

2 个回答

  • Voted
  1. Best Answer
    Nowhere Man
    2023-03-27T16:36:57Z2023-03-27T16:36:57Z

    看起来您是在动态计算组的开始时间而不是从第一个参考日期开始,这意味着您的最小日期值在您浏览列表时会发生变化,因此组数也会发生变化。

    在这方面,forEach不建议使用 Stream API / with a lambda 来构建这样的映射,因为这里需要记住流外的某个状态(参考日期),即要求 lambda 中的变量必须有效 final 被违反。

    但是,您可以简单地遍历按日期排序的输入列表并使用computeIfAbsent. 列表第一个元素的日期作为初始关键日期。然后循环计算这个日期和当前元素的日期之间的天数差异,如果这个差异不满足指定条件(例如超过 14 天),则更新关键日期。

    实施示例:

    record Item(int id, LocalDate date) {}
    
    public static Map<LocalDate, List<Item>> groupByDays(List<Item> items, int days) {
        items.sort(Comparator.comparing(Item::date));
        
        LocalDate keyDate = items.get(0).date();
        
        Map<LocalDate, List<Item>> groups = new LinkedHashMap<>();
        for (Item i : items) {
            keyDate = ChronoUnit.DAYS.between(keyDate, i.date()) < days ? keyDate : i.date();
            groups.computeIfAbsent(keyDate, k -> new ArrayList<>()).add(i);
        }
        return groups;
    }
    

    测试:

    List<Item> items = Arrays.asList(
        new Item(1, LocalDate.of(2023, 3, 1)),
        new Item(2, LocalDate.of(2023, 3, 14)),
        new Item(3, LocalDate.of(2023, 3, 15)),
        new Item(4, LocalDate.of(2023, 3, 30))
    );
    
    var groups = groupByDays(items, 14);
    groups.forEach((k, v) -> System.out.println(k + ": " + v));
    
    2023-03-01: [Item[id=1, date=2023-03-01], Item[id=2, date=2023-03-14]]
    2023-03-15: [Item[id=3, date=2023-03-15]]
    2023-03-30: [Item[id=4, date=2023-03-30]]
    

    对于这种情况,Item(3, LocalDate.of(2023, 3, 20))将有两组:

    2023-03-01: [Item[id=1, date=2023-03-01], Item[id=2, date=2023-03-14]]
    2023-03-20: [Item[id=3, date=2023-03-20], Item[id=4, date=2023-03-30]]
    

    解决方案 cforEach可以使用数组来编写(对数组本身的引用将是最终的),但这被认为是一个技巧:

    public static Map<LocalDate, List<Item>> groupByDaysLambda(List<Item> items, int days) {
        items.sort(Comparator.comparing(Item::date));
    
        Map<LocalDate, List<Item>> groups = new LinkedHashMap<>();
    
        LocalDate[] keyDate = {items.get(0).date()};
        
        items.forEach(i -> groups.computeIfAbsent(
                keyDate[0] = ChronoUnit.DAYS.between(keyDate[0], i.date()) < days ? keyDate[0] : i.date(), 
                k -> new ArrayList<>()
            ).add(i)
        );
    
        return groups;
    }
    

    与流类似,-- 仅适用于顺序有序流,否则结果将不可预测:

    public static Map<LocalDate, List<Item>> groupByDaysStream(List<Item> items, int days) {
        items.sort(Comparator.comparing(Item::date));
    
        LocalDate[] keyDate = {items.get(0).date()};
        
        return items.stream()
            .collect(Collectors.groupingBy(
                i -> keyDate[0] = ChronoUnit.DAYS.between(keyDate[0], i.date()) < days ? keyDate[0] : i.date(),
                LinkedHashMap::new,
                Collectors.toList()
            ));
    }
    
    • 1
  2. Sergey Mitrofanov
    2023-03-27T16:47:32Z2023-03-27T16:47:32Z

    如果日期和期间结束时间不重要,则可以使用以下公式作为分组参数(номер_недели+1)/2。加 1 是必要的,这样第一周就不会成为“孤儿”。然后日期 1-2、3-4 等等将归为一组。

    该方法适用于一年内的日期。您还应该考虑过渡规则,当一月一日的周数可能在上一年的最后一周。

        @Test
        void groupBy2WeekTest() {
            record Item(Integer id, LocalDate published) {
            }
            var items = List.of(
                new Item(1, LocalDate.of(2023, 3, 27)),
                new Item(2, LocalDate.of(2023, 4, 1)),
                new Item(3, LocalDate.of(2023, 4, 5)),
                new Item(4, LocalDate.of(2023, 3, 6)),
                new Item(5, LocalDate.of(2023, 3, 17)),
                new Item(6, LocalDate.of(2023, 3, 23)),
                new Item(7, LocalDate.of(2023, 3, 13)),
                new Item(8, LocalDate.of(2023, 3, 26))
            );
            TemporalField woy = WeekFields.of(Locale.getDefault()).weekOfWeekBasedYear();
            var result = items.stream().collect(Collectors.groupingBy(i -> ((i.published().get(woy))+1)/2));
            result.forEach((g,o) -> System.out.println(g+"\n=============\n"+o));
        }
    
    • 0

相关问题

  • wpcap 找不到指定的模块

  • 如何以编程方式从桌面应用程序打开 HTML 页面?

  • Android Studio 中的 R.java 文件在哪里?

  • HashMap 初始化

  • 如何使用 lambda 表达式通过增加与原点的距离来对点进行排序?

  • 最大化窗口时如何调整元素大小?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5