我有这个清单(List<String>
):
["a", "b", null, "c", null, "d", "e"]
我想要这样的东西:
[["a", "b"], ["c"], ["d", "e"]]
换句话说,我想使用null
值作为分隔符将列表拆分为子列表,以获得列表列表(List<List<String>>
)。我正在寻找Java
8解决方案。我已经尝试过,Collectors.partitioningBy
但是我不确定这是我要找的东西。谢谢!
我目前想出的唯一解决方案是实现自己的自定义收集器。
在阅读解决方案之前,我想添加一些有关此的注释。我将这个问题更多地当作编程练习,我不确定是否可以使用并行流来完成。
因此,您必须意识到,如果 并行* 运行管道,它将 无声地中断 。 *
这 不是 理想的行为,应该 避免 。这就是为什么我在组合器部分(而不是(l1, l2) -> {l1.addAll(l2); return l1;}
)中引发异常,因为在组合两个列表时会并行使用它,以便您有一个异常而不是错误的结果。
同样,由于列表复制,这种方法也不是很有效(尽管它使用本机方法来复制基础数组)。
因此,这是收集器的实现:
private static Collector<String, List<List<String>>, List<List<String>>> splitBySeparator(Predicate<String> sep) {
final List<String> current = new ArrayList<>();
return Collector.of(() -> new ArrayList<List<String>>(),
(l, elem) -> {
if (sep.test(elem)) {
l.add(new ArrayList<>(current));
current.clear();
}
else {
current.add(elem);
}
},
(l1, l2) -> {
throw new RuntimeException("Should not run this in parallel");
},
l -> {
if (current.size() != 0) {
l.add(current);
return l;
}
);
}
以及如何使用它:
List<List<String>> ll = list.stream().collect(splitBySeparator(Objects::isNull));
输出:
[[a, b], [c], [d, e]]
当JoopEggen的答案出炉时,看来可以并行完成(为此感谢他!)。这样,它将自定义收集器实现简化为:
private static Collector<String, List<List<String>>, List<List<String>>> splitBySeparator(Predicate<String> sep) {
return Collector.of(() -> new ArrayList<List<String>>(Arrays.asList(new ArrayList<>())),
(l, elem) -> {if(sep.test(elem)){l.add(new ArrayList<>());} else l.get(l.size()-1).add(elem);},
(l1, l2) -> {l1.get(l1.size() - 1).addAll(l2.remove(0)); l1.addAll(l2); return l1;});
}
这使有关并行性的段落过时了,但是我将其保留下来,因为它可以很好地提醒您。
请注意,Stream API并不总是可以替代。有些任务使用流更容易且更适合,有些则不是。对于您的情况,您还可以为此创建一个实用程序方法:
private static <T> List<List<T>> splitBySeparator(List<T> list, Predicate<? super T> predicate) {
final List<List<T>> finalList = new ArrayList<>();
int fromIndex = 0;
int toIndex = 0;
for(T elem : list) {
if(predicate.test(elem)) {
finalList.add(list.subList(fromIndex, toIndex));
fromIndex = toIndex + 1;
}
toIndex++;
}
if(fromIndex != toIndex) {
finalList.add(list.subList(fromIndex, toIndex));
}
return finalList;
}
并称它为List<List<String>> list = splitBySeparator(originalList,Objects::isNull);
。
可以改进以检查边缘情况。
问题:如何将列表拆分为两个子列表,其中元素由元素中的选项卡分隔? 上下文:我想读取一个由制表符分隔的文件到Pandas DataFrame中。这些文件看起来像: 列1\t 123 列2\t 列3\t文本 这意味着每行有一列,后面跟着一个选项卡,然后是该列的一个值(有时没有值)。 我的想法是读取文件并将每行保存为列表的元素,然后将列表分成两个,将选项卡前的第一部分作为一个列表,选项卡后的第二部分作为
我有一个对象(Pos)与此模型的集合: 对象列表如下所示: 我想按beforeChangement或afterChangement==”字段拆分此对象列表要使用此格式(列表列表)
问题内容: 我有大量的这种格式的元组列表。每个元组的第二个字段是类别字段。 将其分解为相同类别(A,B,C等)的子列表的最有效方法是什么? 问题答案: 使用itertools.groupby: 产量 或者,要创建一个将每个组作为子列表的列表,可以使用列表理解: to的第二个参数是一个适用于(第一个参数)中每个项目的函数。预期会传回。然后将相同的所有连续项目组合在一起。 operator.itemg
如何将这列列表拆分为两列? 期望的结果:
我有一个包含字典作为元素的单列的。这是以下代码的结果: 我需要将此列拆分为尽可能多的列(我有太多的行和列,并且我无法更改函数),因此输出将是一个包含列,,的数据帧,<代码>功能50。这样做的最佳方式是什么? 一个具体而简单的例子: 但当我尝试用pd.Series或pd.DataFrame包装它时,它说如果数据是标量值,则必须提供索引。提供索引=['feature1','feature2'],我会得
我有一个非常简单的,其中每个单元格都包含一个列表。我想将列表中的每个元素拆分为它自己的列。我可以通过导出值,然后创建一个新的