2016-05-11 49 views
0

我需要一些示例代碼或算法來調整List<List<Integer>>應在下一工作方式的數量:爪哇 - 調整嵌套列表

讓我們想象一下,我們有下一個newSizeincomingList(僞):

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整數集的incomingListresizeListOfNestedList新大小應返回下一個結果爲非奇數(例如,4):

List(List(1,2),List(3,4),List(5,6),List(7,8) 

和下如果新尺寸是奇數(例如3):

List(List(1,2),List(3,4,5),List(6,7,8) 

newSize總是大於incomingList.size()

我希望任何建議。

更新

隨着google.common.Lists幫助下,我已經完成守則草案(是的,聞起來),我希望它會幫助別人。

在我的案例方法接收不同incomingList.size() S和newSize PARAMS和很明顯,incomingList.size()/newSize將返回雙精度值(例如,進入則爲list.size()= 1000,但我們需要「壓縮」它600元),所以我無法始終使用Lists.partitionexpandList是更好的下一個代碼後致電:

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; 
     } 
    } 
+0

請告訴我們您到目前爲止所嘗試過的。 – eltabo

+0

@eltabo如果我有一些有用的代碼草稿,我會用問題發佈它。請注意,我沒有要求完整的解決方案。另外,我想應該有一些java庫可以幫助。 – unpc

+0

任務不夠清楚,您是不是在示例中丟失了9的值? –

回答

1

您可以直接對其進行編碼,純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; 
} 
0

你爲什麼不從Apache Commons使用ListUtils.union(list1,list2);

Java: how can I split an ArrayList in multiple small ArrayLists?

+0

謝謝你的迴應。在我的情況下,我不知道塊大小。例如方法接收數組大小1000,並要求嵌套列表大小應爲600個元素。如果你嘗試計算塊,你會得到雙'1,66',不能傳遞給'分區(列表列表,int大小)'。這就是爲什麼我將塊舍入到上限值,分割,然後擴展到所需的大小。 – unpc

1

閱讀你的問題,我可以拿出做2步的算法思想:

  1. 將所有的子表到一個列表(使用Guava Iterables
  2. 分區第1步(使用Guava partition)的結果

番石榴有助於更多地關注我們所需要的而不是如何去做,因此很容易翻譯您的僞代碼和工作代碼。

所以,你可以有這樣的事情:

@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 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); 
} 

作爲關於結果列表的註釋,部分ition方法創建N個值的多個列表,但最後一個列表的值可能較少。對於你所說的,似乎你想在開始的時候減少價值。我把它留給你來搜索分區方法和番石榴的用法。