【问题标题】:Custom chunking of Lists Java 8列表 Java 8 的自定义分块
【发布时间】:2017-12-12 07:07:34
【问题描述】:

我有 2 个列表。

List<Integer> data = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> partitionHelper = Arrays.asList(1, 3, 4, 5);

我想使用partitionHelperdata 列表分配成块。 对于上面的例子,输出应该是

List<List<Int>> partition = chunk(data, partitionHelper)
//partition = {{1}, {2,3,4}, {5,6,7,8}, {9,10}}

可以安全地假设partitionHelper.sum() >= data.size()。 我最好需要一个 O(n + m) 算法(其中 n = partitionHelper.size() 和 m = data.size())

关于List&lt;List&lt;T&gt;&gt; chunk(List&lt;T&gt;, List&lt;Integer&gt;) 函数实现应该如何显示的任何指针?

PS:我正在寻找一种功能风格的方法。 不是标准的迭代。

编辑:

在 Scala 中我会做这样的事情

def chunkList(data: List[Int], p: List[Int]): List[List[Int]] = {
  def chunk(data: List[Int], p: List[Int], acc: List[List[Int]]): List[List[Int]] =
    if (p.nonEmpty && data.nonEmpty) {
      chunk(data.drop(p.head), p.tail, acc :+ data.take(p.head))
    } else {
      acc
    }
  chunk(data, p, List())
}

> chunkList((1 to 10).toList, List(1,3,4,5))
> res2: List[List[Int]] = List(List(1), List(2, 3, 4), List(5, 6, 7, 8), List(9, 10))

可以找到另一个用于 foldl 和 foldr 的 Haskell 实现 here

【问题讨论】:

  • 你是什么意思我需要?当你试图自己解决这个问题时发生了什么?你在哪里被屏蔽了?
  • @ApoorvIngle 您的问题是同一问题的变体,您只需为每个分区提供不同的长度。重要的部分是:“不可能对任意源流进行分区 [...],因为这会破坏并行处理。” --- 你的问题是 XY problem。如果要对 List&lt;T&gt; 进行分区,请不要使用 Streams。使用循环和subList() 调用。它的性能也会比任何流式实现都要好得多。
  • @ApoorvIngle 我不了解 Scala,但对我来说这看起来像是一个 recursive 函数实现。如果这就是你想要的,你为什么要求 Java Stream 实现?您可以在 Java 中执行完全相同的递归函数。您所要做的就是编写它。
  • @ApoorvIngle 没有,不在基础 Java 中。流确实是唯一内置的 Java 集合“功能样式”的方法,并且没有真正的方法可以使用流来做到这一点。如果第三方库是游戏的话,不如使用 Guava 的Lists.partition
  • List&lt;List&lt;T&gt;&gt; result = new ArrayList&lt;&gt;(partitionHelper.size()); int i = 0; for (int size : partitionHelper) result.add(data.subList(i, Math.min(i += size, data.size())));

标签: functional-programming java-8 partitioning


【解决方案1】:

将您的 Scala 代码翻译成 Java 后,我得到了以下代码,该代码仅对小型 partitionHelper 列表有用:

List<List<Integer>> chunk(List<Integer> data, List<Integer> p, List<List<Integer>> acc) {
    if (!p.isEmpty() && !data.isEmpty()) {
        int i = Math.min(p.get(0), data.size());
        acc.add(data.subList(0, i));
        return chunk(data.subList(i, data.size()), p.subList(1, p.size()), acc);
    }
    return acc;
}

List<List<Integer>> chunk(List<Integer> data, List<Integer> p) {
    return chunk(new ArrayList<>(data), p, new ArrayList<>());
}

确实,partitionHelper 列表必须很小,因为堆栈正在用于 chunk 方法的递归调用,并且将有与 partitionHelper 列表中的元素一样多的递归调用。

【讨论】:

  • 感谢您的回答,但我正在寻找一种 foldLeft/foldRight 的实现。请查看我添加到问题中的 Haskell 链接
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-25
  • 1970-01-01
  • 2015-09-08
  • 2016-01-25
  • 1970-01-01
  • 2015-02-21
  • 1970-01-01
相关资源
最近更新 更多