Java - 调整嵌套列表的数量
Java - resize number of nested lists
我需要一些代码示例或算法来调整 List<List<Integer>>
的大小,它应该可以在接下来的方式中工作:
假设我们有下一个 newSize
和 incomingList
(伪代码):
int newSize = 4;
List<List<Integer>> incomingList = List(List(1,2,3),List(4,5,6),List(7,8,9);
List<List<Integer>> result = resizeListOfNestedList(newSize, incomingList)
newSize
整数设置 incomingList
的新大小并且 resizeListOfNestedList
应该 return 非奇数的下一个结果(例如 4):
List(List(1,2),List(3,4),List(5,6),List(7,8)
如果 newSize 为奇数(例如 3),则下一步:
List(List(1,2),List(3,4,5),List(6,7,8)
newSize
总是大于 incomingList.size()
如有任何建议,我将不胜感激。
更新
在google.common.Lists
的帮助下,我完成了代码草稿(是的,有点味道),希望对大家有所帮助。
在我的例子中,方法接收不同的 incomingList.size()
s 和 newSize
参数,很明显 incomingList.size()/newSize
将 return 加倍值(例如传入 list.size( ) = 1000,但我们需要 "compress" 到 600 个元素)所以我无法一直使用 Lists.partition
。 expandList
最好在下一个代码之后调用:
int maxSplitValue = (int) Math.ceil((double) incomingList.size() / newSize);
List<List<Integer>> firstPortionValues = Lists.partition(
incomingList, maxSplitValue
);//size can be less than required after double to int upper round
if (firstPortionValues.size() < maxSplitValue) {
List<List<Integer>> expandedList = expandList(firstPortionValues, maxSplitValue)
}
结果:
Incoming list:[[0, 1], [2, 3]]
New size value: 3
Outcoming list:[[0], [1], [2, 3]]
Incoming list:[[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]
New size value: 4
Outcoming list:[[0.0], [1.0], [2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]
代码:
public List<List<Integer>> expandList(List<List<Integer>> incomingList, int newSize) {
List<List<Integer>> resultList = new ArrayList<>();
for (int index = 0; index < incomingList.size(); index++) {
List<Integer> nodeList = incomingList.get(index);
final int minPortionValue = getMinPortionValue(
incomingList.size(), resultList.size(), nodeList.size(), index, newSize
);
List<List<Integer>> portionResult = splitNodeList(new ArrayList<>(nodeList), minPortionValue);
resultList.addAll(portionResult);
}
return resultList;
}
private int getMinPortionValue(int listSize, int resultListSize, int listElementSize, int index, int newSize) {
if (listElementSize > 1) {
int maxPortionValue = listElementSize % 2 == 0 ? listElementSize / 2 : --listElementSize;
boolean isOkUseMaxPortionValue = maxPortionValue + listSize - index + resultListSize <= newSize;
if (isOkUseMaxPortionValue) {
return maxPortionValue;
} else {
return getMinPortionValue(listSize, resultListSize, listElementSize - 1, index, newSize);
}
} else {
return 0;
}
}
private List<List<Integer>> splitNodeList(List<Integer> nodeList, int minSplitValue) {
List<List<Integer>> result = new ArrayList<>();
if (minSplitValue > 0) {
result.addAll(Lists.partition(nodeList, minSplitValue));
return result;
} else {
result.add(nodeList);
return result;
}
}
为什么不使用 Apache Commons 和
中的 ListUtils.union(list1,list2);
Java: how can I split an ArrayList in multiple small ArrayLists?
看了你的问题,我可以想出做两步的算法思路:
- 将所有子列表合并为一个列表(使用Guava Iterables)
- 对步骤 1 的结果进行分区(使用 Guava partition)
Guava 有助于更多地关注我们需要什么而不是如何去做,因此很容易翻译您的伪代码和工作代码。
所以,你可以有这样的东西:
@Test
public void test(){
// Init lists
List<Integer> a = Lists.newArrayList(1,2,3);
List<Integer> b = Lists.newArrayList(4,5,6);
List<Integer> c = Lists.newArrayList(7,8,9);
List<List<Integer>> incomingList = Lists.newArrayList(a,b,c);
System.out.println(incomingList);
// Create combined list
Iterable<Integer> tempList = Iterables.concat(incomingList);
// Re-Partition list
Iterable<List<Integer>> result = Iterables.partition(tempList, 2); // New size: 2
// Convert from Iterables to List
List<List<Integer>> finalList = Lists.newArrayList(result);
System.out.println(finalList);
}
输出为:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]] // Incoming list
[[1, 2], [3, 4], [5, 6], [7, 8], [9]] // Final list
以上代码是为了便于调试,您可以减少代码行数,并利用 import static 使其更具可读性并具有以下特点:
import static com.google.common.collect.Iterables.*;
import static com.google.common.collect.Lists.*;
public void test(){
List<Integer> a = newArrayList(1,2,3);
List<Integer> b = newArrayList(4,5,6);
List<Integer> c = newArrayList(7,8,9);
List<List<Integer>> incomingList = newArrayList(a,b,c);
System.out.println(incomingList);
// Repartition
List<List<Integer>> finalList = newArrayList(partition(concat(incomingList), 2));
System.out.println(finalList);
}
作为对结果列表的说明,分区方法会创建多个包含 N 个值的列表,但最后一个列表可以包含更少的值。对于您所说的,您一开始似乎想要更少的价值。我留给你搜索分区方法和番石榴用法。
您可以直接编码,纯粹 Java7。此代码使新的列表列表保持平衡,最后添加额外的元素。
public List<List<Integer>> resizeListOfNestedList(int newSize, List<List<Integer>> data) {
ArrayList<Integer> allElements = new ArrayList<>();
for (List<Integer> integers : data) {
allElements.addAll(integers);
}
int elementsPerItem = allElements.size() / newSize;
int extraElements = allElements.size() % newSize;
int indexToStartAddExtraElement = newSize - extraElements;
ArrayList<List<Integer>> result = new ArrayList<>(newSize);
Iterator<Integer> iterator = allElements.iterator();
for (int i = 0; i < newSize; i++){
int currentItemElementsCount = elementsPerItem;
if (i >= indexToStartAddExtraElement)
currentItemElementsCount++;
ArrayList<Integer> current = new ArrayList<>(currentItemElementsCount);
for (int j = 0; j < currentItemElementsCount; j++){
current.add(iterator.next());
}
result.add(current);
}
return result;
}
我需要一些代码示例或算法来调整 List<List<Integer>>
的大小,它应该可以在接下来的方式中工作:
假设我们有下一个 newSize
和 incomingList
(伪代码):
int newSize = 4;
List<List<Integer>> incomingList = List(List(1,2,3),List(4,5,6),List(7,8,9);
List<List<Integer>> result = resizeListOfNestedList(newSize, incomingList)
newSize
整数设置 incomingList
的新大小并且 resizeListOfNestedList
应该 return 非奇数的下一个结果(例如 4):
List(List(1,2),List(3,4),List(5,6),List(7,8)
如果 newSize 为奇数(例如 3),则下一步:
List(List(1,2),List(3,4,5),List(6,7,8)
newSize
总是大于 incomingList.size()
如有任何建议,我将不胜感激。
更新
在google.common.Lists
的帮助下,我完成了代码草稿(是的,有点味道),希望对大家有所帮助。
在我的例子中,方法接收不同的 incomingList.size()
s 和 newSize
参数,很明显 incomingList.size()/newSize
将 return 加倍值(例如传入 list.size( ) = 1000,但我们需要 "compress" 到 600 个元素)所以我无法一直使用 Lists.partition
。 expandList
最好在下一个代码之后调用:
int maxSplitValue = (int) Math.ceil((double) incomingList.size() / newSize);
List<List<Integer>> firstPortionValues = Lists.partition(
incomingList, maxSplitValue
);//size can be less than required after double to int upper round
if (firstPortionValues.size() < maxSplitValue) {
List<List<Integer>> expandedList = expandList(firstPortionValues, maxSplitValue)
}
结果:
Incoming list:[[0, 1], [2, 3]]
New size value: 3
Outcoming list:[[0], [1], [2, 3]]
Incoming list:[[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]
New size value: 4
Outcoming list:[[0.0], [1.0], [2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]]
代码:
public List<List<Integer>> expandList(List<List<Integer>> incomingList, int newSize) {
List<List<Integer>> resultList = new ArrayList<>();
for (int index = 0; index < incomingList.size(); index++) {
List<Integer> nodeList = incomingList.get(index);
final int minPortionValue = getMinPortionValue(
incomingList.size(), resultList.size(), nodeList.size(), index, newSize
);
List<List<Integer>> portionResult = splitNodeList(new ArrayList<>(nodeList), minPortionValue);
resultList.addAll(portionResult);
}
return resultList;
}
private int getMinPortionValue(int listSize, int resultListSize, int listElementSize, int index, int newSize) {
if (listElementSize > 1) {
int maxPortionValue = listElementSize % 2 == 0 ? listElementSize / 2 : --listElementSize;
boolean isOkUseMaxPortionValue = maxPortionValue + listSize - index + resultListSize <= newSize;
if (isOkUseMaxPortionValue) {
return maxPortionValue;
} else {
return getMinPortionValue(listSize, resultListSize, listElementSize - 1, index, newSize);
}
} else {
return 0;
}
}
private List<List<Integer>> splitNodeList(List<Integer> nodeList, int minSplitValue) {
List<List<Integer>> result = new ArrayList<>();
if (minSplitValue > 0) {
result.addAll(Lists.partition(nodeList, minSplitValue));
return result;
} else {
result.add(nodeList);
return result;
}
}
为什么不使用 Apache Commons 和
中的ListUtils.union(list1,list2);
Java: how can I split an ArrayList in multiple small ArrayLists?
看了你的问题,我可以想出做两步的算法思路:
- 将所有子列表合并为一个列表(使用Guava Iterables)
- 对步骤 1 的结果进行分区(使用 Guava partition)
Guava 有助于更多地关注我们需要什么而不是如何去做,因此很容易翻译您的伪代码和工作代码。
所以,你可以有这样的东西:
@Test
public void test(){
// Init lists
List<Integer> a = Lists.newArrayList(1,2,3);
List<Integer> b = Lists.newArrayList(4,5,6);
List<Integer> c = Lists.newArrayList(7,8,9);
List<List<Integer>> incomingList = Lists.newArrayList(a,b,c);
System.out.println(incomingList);
// Create combined list
Iterable<Integer> tempList = Iterables.concat(incomingList);
// Re-Partition list
Iterable<List<Integer>> result = Iterables.partition(tempList, 2); // New size: 2
// Convert from Iterables to List
List<List<Integer>> finalList = Lists.newArrayList(result);
System.out.println(finalList);
}
输出为:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]] // Incoming list
[[1, 2], [3, 4], [5, 6], [7, 8], [9]] // Final list
以上代码是为了便于调试,您可以减少代码行数,并利用 import static 使其更具可读性并具有以下特点:
import static com.google.common.collect.Iterables.*;
import static com.google.common.collect.Lists.*;
public void test(){
List<Integer> a = newArrayList(1,2,3);
List<Integer> b = newArrayList(4,5,6);
List<Integer> c = newArrayList(7,8,9);
List<List<Integer>> incomingList = newArrayList(a,b,c);
System.out.println(incomingList);
// Repartition
List<List<Integer>> finalList = newArrayList(partition(concat(incomingList), 2));
System.out.println(finalList);
}
作为对结果列表的说明,分区方法会创建多个包含 N 个值的列表,但最后一个列表可以包含更少的值。对于您所说的,您一开始似乎想要更少的价值。我留给你搜索分区方法和番石榴用法。
您可以直接编码,纯粹 Java7。此代码使新的列表列表保持平衡,最后添加额外的元素。
public List<List<Integer>> resizeListOfNestedList(int newSize, List<List<Integer>> data) {
ArrayList<Integer> allElements = new ArrayList<>();
for (List<Integer> integers : data) {
allElements.addAll(integers);
}
int elementsPerItem = allElements.size() / newSize;
int extraElements = allElements.size() % newSize;
int indexToStartAddExtraElement = newSize - extraElements;
ArrayList<List<Integer>> result = new ArrayList<>(newSize);
Iterator<Integer> iterator = allElements.iterator();
for (int i = 0; i < newSize; i++){
int currentItemElementsCount = elementsPerItem;
if (i >= indexToStartAddExtraElement)
currentItemElementsCount++;
ArrayList<Integer> current = new ArrayList<>(currentItemElementsCount);
for (int j = 0; j < currentItemElementsCount; j++){
current.add(iterator.next());
}
result.add(current);
}
return result;
}