根据唯一值将列表拆分为子列表

Posted

技术标签:

【中文标题】根据唯一值将列表拆分为子列表【英文标题】:Splitting List into sublists based on unique values 【发布时间】:2015-05-13 14:57:35 【问题描述】:

我有一个列表列表: List<ArrayList<String>> D = new ArrayList<>();

填充后,它可能看起来像: [“A”、“B”、“Y”] [“C”、“D”、“Y”] [“A”、“D”、“N”]

我想根据唯一的属性值(假设索引 1)将列表列表拆分为分区。

所以索引 1 处的属性有两个唯一值,“B”和“D”,所以我想拆分为: [“A”、“B”、“Y”]

[“C”、“D”、“Y”] [“A”、“D”、“N”]

并将它们放入List<ArrayList<ArrayList<String>>> sublists;

有没有一种聪明的方法可以做到这一点,或者我只是做这样的事情:

List<ArrayList<ArrayList<String>>> sublists = new ArrayList<>();
int featIdx = 1;

// generate the subsets
for (ArrayList<String> record : D) 
    String val = record.get(featIdx);

    // check if the value exists in sublists
    boolean found = false;
    for (ArrayList<ArrayList<String>> entry : sublists) 
        if (entry.get(0).get(featIdx).equals(val)) 
            entry.add(record);
            found = true;
            break;
        
    

    if (!found) 
        sublists.add(new ArrayList<>());
        sublists.get(sublists.size()-1).add(record);
    

这是 C4.5 决策树 algorithm 的一个步骤,所以如果有人有这方面的经验,如果你能告诉我这是否是生成子列表的正确方法,我将不胜感激。

谢谢。

【问题讨论】:

【参考方案1】:

我建议创建一个HashMap&lt;String, List&lt;List&lt;String&gt;&gt;&gt;,并将这些列表分组。然后只需拨打map.values() 即可获得Collection&lt;List&lt;List&lt;String&gt;&gt;&gt;

List<List<String>> list = new ArrayList<>();
list.add(Lists.newArrayList("A", "B", "Y"));
list.add(Lists.newArrayList("C", "D", "Z"));
list.add(Lists.newArrayList("A", "D", "X"));
list.add(Lists.newArrayList("D", "C", "A"));

Map<String, List<List<String>>> mapped = list.stream()
                .collect(Collectors.groupingBy(li -> li.get(1))); 
System.out.println(mapped);
Collection<List<List<String>>> groupedList = mapped.values();

【讨论】:

【参考方案2】:

在 Java 8 中,您可以使用 groupingBy 收集器:

Map<String, List<List<String>>> grouped = D.stream()
                .collect(Collectors.groupingBy(list -> list.get(1)));
Collection<List<List<String>>> sublists = grouped.values();

或按照@AlexisC 的建议:

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.groupingBy;

Collection<List<List<String>>> sublists = D.stream()
             .collect(collectingAndThen(groupingBy(list -> list.get(1)), Map::values));

【讨论】:

.. 或Collection&lt;List&lt;List&lt;String&gt;&gt;&gt; subLists = D.stream().collect(collectingAndThen(groupingBy(x -&gt; x.get(1)), Map::values)); 虽然,在这种情况下,我怀疑与你所做的有很大的不同(如果你在 collect 之后直接调用值) 我猜,collectingAndThen 仅在将生成的 Collector 传递到另一个复合 Collector 时才有用。否则,这只是在结果上调用方法的一种更复杂的方式。

以上是关于根据唯一值将列表拆分为子列表的主要内容,如果未能解决你的问题,请参考以下文章

根据列中的共同值将大数据框拆分为数据框列表

Python:根据索引范围将列表拆分为子列表

python - 如何首先根据初始列表的单个元素将列表拆分为子列表,然后在python中将列表的连续部分拆分为子列表?

按列值将数据框拆分为两个[重复]

将数组拆分为子数组5次,同时在所有子数组中保持唯一对]]

如何提取/拆分数据框中的列表列以分隔唯一列?