我想将列表均匀分配到给定数量的子列表中。 例如,我有一个包含元素1到10的列表,我想要3个列表。这些看起来应该是:
SL1 -> {1, 2, 3, 4}
SL2 -> {5, 6, 7}
SL3 -> {8, 9, 10}
重要:每个列表包含的内容不相关,即SL1可能具有{1,5,7,10}。最重要的是有2个大小为3的列表和1个大小为4的列表。
我尝试了几件事,包括Iterables.partition
,但这无济于事。
我唯一能想到的是:
public Iterable<List<Integer>> distributeEvenlyQueryListIntoLists(final LinkedList<Integer> bigList, final Integer numberOfSublists) {
List<List<Integer>> result = new ArrayList<>();
// Creates as many lists as needed
for (int i = 0; i < numberOfSublists; i++) {
result.add(new ArrayList<>());
}
while (bigList.iterator().hasNext()) {
for (int i = 0; i < numberOfSublists; i++) {
if (!bigList.iterator().hasNext()) {
break;
}
result.get(i).add(bigList.poll());
}
}
return result;
}
传递的bigList
不一定是LinkedList
,也可以是Iterable
。
我特别讨厌创建子列表的第一个循环。
谢谢!
答案 0 :(得分:5)
只需以循环模式分发它们:
public <T> List<List<T>> partition(Iterable<T> iterable, int partitions){
List<List<T>> result = new ArrayList<>(partitions);
for(int i = 0; i < partitions; i++)
result.add(new ArrayList<>());
Iterator<T> iterator = iterable.iterator()
for(int i = 0; iterator.hasNext(); i++)
result.get(i % partitions).add(iterator.next());
return result;
}
使用此代码运行的示例:
List<String> l = Stream.iterate(0, i->i + 1).limit(25).map(i->Integer.toString(i)).collect(Collectors.toList());
System.out.println(partition(l, 4).toString());
可生产
[[0,4,8,12,16,20,24],[1,5,9,13,17,21],[2,6,10,14,18,22],[3] ,7,11,15,19,23]]
基本思想是向结果集中的每个列表添加一个元素。这样就可以保证两个列表之间元素数量的差异不会超过1。
作为替代方案,您可以使用Iterables.partition的guavas实现,这需要稍微不同的方法。
答案 1 :(得分:2)
如果您讨厌创建子列表,这意味着您正在寻找快速解决方案。 如果您拥有原始List
,并且计划不改变原始List
,请考虑List.subList()
。
int subSize = bigList.length() / numSubs;
int numBigSubs = 0; // # of subs that need to be one bigger
if (bigList.length() % numSubs > 0) {
subSize++;
numBigSubs = bigList.length() % numSubs;
}
int from = 0;
int to = subSize;
List<List<Integer>> subList = new ArrayList<List<Integer>>(numSubs);
for (int i = 0; i < numSubs; i++) {
List<Integer> newSub = bigList.subList(from, to);
subList.add (newSub);
from = to;
to += subSize;
if (i >= numBigSubs && numBigSubs > 0) to--;
}
注意:我在没有测试的情况下写了这个 - 如果它失败了,我道歉,并希望有人会编辑它来工作。
同样,这方面的最大好处是它应该是快速的 - 所有的子列表只是对较大的一个的观点。缺点是,如果您更改列表,则所有投注均已关闭。