【发布时间】: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);
我想使用partitionHelper 将data 列表分配成块。
对于上面的例子,输出应该是
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<List<T>> chunk(List<T>, List<Integer>) 函数实现应该如何显示的任何指针?
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<T>进行分区,请不要使用 Streams。使用循环和subList()调用。它的性能也会比任何流式实现都要好得多。 -
@ApoorvIngle 我不了解 Scala,但对我来说这看起来像是一个 recursive 函数实现。如果这就是你想要的,你为什么要求 Java Stream 实现?您可以在 Java 中执行完全相同的递归函数。您所要做的就是编写它。
-
@ApoorvIngle 没有,不在基础 Java 中。流确实是唯一内置的 Java 集合“功能样式”的方法,并且没有真正的方法可以使用流来做到这一点。如果第三方库是游戏的话,不如使用 Guava 的
Lists.partition。 -
List<List<T>> result = new ArrayList<>(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