【问题标题】:Creating a sub-List of size N from an existing ArrayList从现有的 ArrayList 创建大小为 N 的子列表
【发布时间】:2018-08-25 20:20:32
【问题描述】:

我正在学习 Jjava,我在 ArrayLists 上发现了一个有趣的练习。目的是编写一个函数partition(),它接受一个参数list和一个参数size,并返回一个子列表列表,其中每个子列表有最大的size元素。

例如:

  • partition([1,2,3,4,5], 2) 应该返回 [ [1,2], [3,4], [5] ]
  • partition([1,2,3,4,5], 3) 应该返回 [ [1,2,3], [4,5] ]
  • partition([1,2,3,4,5], 1) 应该返回 [ [1], [2], [3], [4], [5] ]

我这样做了,但它只有在参数 size 等于 1 时才有效,并且我想在所有情况下都这样做,如果有人可以帮助我,我正在努力。

public static void main(String[] args) {
    Apside t = new Apside();
    ArrayList<Integer> a = new ArrayList<Integer>();
    a.add(1);
    a.add(2);
    a.add(3);
    a.add(4);
    System.out.println(t.partition(a, 1));
}

public ArrayList<ArrayList> partition(ArrayList<Integer> l, int n) {
    ArrayList<ArrayList> al = new ArrayList();
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < l.size(); j++) {
            for(int k =0; k<n; k++){
                ArrayList<Integer> list = new ArrayList(n);
                int b = l.get(j);
                list.add(b);
                al.add(list);
            }



        }
    }
    return al;
}

【问题讨论】:

标签: java list arraylist


【解决方案1】:

你可以使用 subList 方法。

public ArrayList<ArrayList> partition(List<Integer> li, int n) {
    ArrayList<ArrayList> al = new ArrayList();
    int start = 0;
    int i=n;
    for(; i<li.size(); i+=n){
        List<Integer> lis = li.subList(start, i);
        ArrayList<Integer> list = new ArrayList<>();
        list.addAll(lis);
        al.add(list);
        start = i;
    }

    if(i >= li.size()){
        List<Integer> lis = li.subList(start, li.size());
        ArrayList<Integer> list = new ArrayList<>();
        list.addAll(lis);
        al.add(list);
    }
    return al;
}

【讨论】:

  • 它成功了,我只是要调试代码以理解谢谢
【解决方案2】:

我试图了解您的解决方案,但不幸的是我不明白。你的外层循环是错误的:最外层的循环绝对应该是从 0 到列表的大小,而不是分区的大小。

接下来是你最内层的循环。每次您在里面创建一个新列表时,向其中添加一个元素并将此列表添加到您的结果中。这没有任何意义。很可能你想要这样的东西(中间循环的主体)

List<Integer> list = new ArrayList<Integer>(n);
for (...) {
    ...
    int b = l.get(j);
    list.add(b);
    ...
}
al.add(list);

但它仍然不起作用,因为您引入了第三个循环,这里绝对不需要。为了使您的解决方案可靠,您只需要 2 个循环(第一个 - 遍历整个列表,第二个遍历当前分区:

public static List<List<Integer>> partition(List<Integer> l, int n) {
    List<List<Integer>> al = new ArrayList<>();
    for (int i = 0; i < l.size(); i += n) {
        List<Integer> list = new ArrayList<>();
        for (int j = i; j < i + n && j < l.size(); j++) {
            list.add(l.get(j));
        }
        al.add(list);
    }
    return al;
}

看看我选择的边界:外循环从 0 到列表的大小,步长为分区大小,而内循环从外循环的当前索引到分区大小或列表大小,以先到者为准。

有一个更简单的解决方案:

private static List<List<?>> partition(List<?> list, int size) {
    var result = new ArrayList<List<?>>();
    for (int i = 0; i < list.size(); i += size) {
        result.add(new ArrayList<>(list.subList(i, Math.min(i + size, list.size()))));
    }
    return result;
}

这是一种通用方法,您可以传递任何元素(不仅仅是整数)的列表并获得分区结果。这里又是一个循环,从 0 到列表大小,有一个分区大小步长,每次根据分区大小获取原始列表的子列表,如果分区不足,则只获取剩余元素。

另外,作为旁注。看看我的代码使用接口 (List) 而不是实现 (ArrayList) 并使用泛型类型 (ArrayList&lt;&gt;(), List&lt;Integer&gt;(), List&lt;?&gt; 而不是原始类型 (ArrayList())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 2019-08-07
    相关资源
    最近更新 更多