2015-05-28 24 views
8

Ben listelerin listesi var.Birden çok listelerindeki öğelerin sayısını bulun ve birleştirin;/else kompleksi kaldırılsın mı?</p> <pre><code>List<List<String>> someList = new List<List<>>(); </code></pre> <p>bir liste maksimum boyutu beş dizeleri geçerli:

someList.get(0).size(); // 4 elements 
someList.get(1).size(); // 1 elements 
someList.get(2).size(); // 3 elements 
someList.get(3).size(); // 1 elements 
... 

Yukarıda iç içe listelerin bazıları birleştirerek belirli boyut (1-5 elemanları) yeni bir liste oluşturmak için bir yöntem bulmak çalışıyorum: Aşağıda gibi bir şey. Ben büyüklüğü 1 üçünü bulmak için hiçbir Alt listeler, boyut 2'nin ise için döngü dahil etmedik

public List<String> getThree() { 
    for (int j = 0; j < someList.size(); j++) { 
     //look for nested lists of size 3 
     if (someList.get(j).size() == 3) { 
      return someList.get(j); 
     } 
    for (int j = 0; j < someList.size(); j++) { 
     //if found nested list of size 2, find one of size 1 to combine 
     if (someList.get(j).size() == 2) { 
      for (int k = 0; k < someList.size(); k++) { 
       if (someList.get(k).size() == 1) { 
        return someList.get(j).add(someList.get(k).get(0)); 
       } 
      } 
     } 
    for (int j = 0; j < someList.size(); j++) { 
     //if found nested list of size 1, find one of size 2 to combine 
     if (someList.get(j).size() == 1) { 
      for (int l = 0; l < someList.size(); l++) { 
       if (someList.get(l).size() == 2) { 
        return someList.get(j).addAll(someList.get(l)); 
       } 
      } 
     } 
    } 
} 

ancak hayal edebilirsiniz: I (bu örnekte, üç unsurun) altına böyle bir şey yapabileceğini ne kadar uzun ve ne kadar çirkin olabilir. Sıralama önemlidir, bu nedenle sıralı olarak artan ilmekler için (yani, altList 1 + 2'yi 2 + 3'den, 1 + 3'ten 2 + 3'den daha çok, vs. birleştirmeyi tercih ederim).

Bunu dinamik olarak uygulamak için bir yol bulmayı umuyorum. Sadece okunamayan ve uzun olan getFive metodunun benim mevcut metodolojimi sağladığını anlayabiliyorum. Birden fazla yönteme sahibim (getOne aracılığıyla getFive), bu anlamda dinamik olmamıza gerek yok, sadece bir çok şeyden kurtulmak isterim ve karmaşıklığı azaltmak ve okunabilirliği artırmak için döngüler olsun. Bu ödevim ile ilgili olduğundan bahsetmeliyim, bu yüzden tam olarak belirli bir cevap istemiyorum, fakat doğru yönde bir dürtme istemiyorum. Belki bir şey modulo? Kalanlarla mı?

edit; açıklık ve bir örnek elde edildi:

aList = new List<String>; 
aList.add("a"); 
aList.add("b"); 
someList.add(aList); 
bList = new List<String>; 
bList.add("c"); 
someList.add(bList); 
newList = someList.getThree(); 
//newList.size() == 3 
//newList contains "a","b","c" 

getThree() yöntem someList arasında sublists elemanların oluşan yeni bir listesini yaratıyor. Bir alt listeyi bölemez (yani, 2 elementin bir alt listesinden 1 element alamaz), tüm alt listeleri birleştirir.

+0

Listeler listesini tek bir listeye dönüştürmeye mi çalışıyorsunuz? Bu hakkı anlıyor muyum? – Forseth11

+1

Bir saat kadar beklemek zorundayım, ve eğer bu soruya cevap vermiyorsa, sana bir cevabım olduğunu düşünüyorum. – Forseth11

+0

Hangi listeleri birleştirdiğiniz ve öğelerin hangi sırada olduğu önemli mi? {1, 3, 2, 4, 1} 'boyutlarına sahip myList öğeniz olduğunu ve sonuçta oluşan" size = 5 "listesinin olmasını istediğinizi, aşağıdaki kombinasyonların tümü çözüm olarak değerlendirdiğini varsayalım? {1 + 3 + 1}, {3 + 2}, {4 + ya da 1}. – mkobit

cevap

3

halinde Amacınız ardışık li toplamaya devam etmektir Eğer 5 elemanlarını elde edene kadar STS, listeniz dolduğunda sonra patlak eklemeye devam:

Collections.sort(sources, (a, b) -> b.size() - a.size()); 
: Eğer ilk büyük listeleri tüketmek yöntemin ilk satırı olarak eklemek istiyorsanız

public static List<String> fill(List<List<String>> sources, int size) { 
    List<String> list = new ArrayList<>(); 
    for (List<String> source : sources) 
     if (source.size() <= size - list.size()) 
      list.addAll(source); 
    return list; 
} 

java 8'de


oldukça özlü:

public static List<String> fill(List<List<String>> sources, int size) { 
    return sources.stream().reduce(new ArrayList<>(), 
     (a, b) -> {if (b.size() <= a.size() - size) a.addAll(b); return a;}); 
} 

ve en büyük birinci mod ile

:

public static List<String> fill(List<List<String>> sources, int size) { 
    return sources.stream() 
     .sorted((a,b) -> b.size() - a.size()) 
     .reduce(new ArrayList<>(), (a, b) -> 
      {if (b.size() <= a.size() - size) a.addAll(b); return a;}); 
} 
+0

@ Shar1er80 Bunu fark etmedim. Aslında buna izin vermek kodu çok daha basit hale getirir. Düzenlenmiş kod şimdi OP'nin ne istediğini düşünüyor mu? – Bohemian

+0

Çözümünüzü daha iyi seviyorum, şimdi OP'nin niyetlerini daha iyi anladığımı düşünüyorum. Her çağrı yapıldığında aynı sonucu döndürmenin amacını anlamıyorum. Bence birleşik kalıcı olacak ve geçici olmayacaktır, çünkü bir alt listeyi asla geri dönüş sonucunun bir parçası olarak görmeyeceğiniz durumlar olabilir. – Shar1er80

+0

Örneğin, OP'nin {4, 1, 3, 1} örneklerinin listesinde, potansiyel getOne() öğesine yapılan her çağrı, her zaman dizin 1'deki alt liste ile sonuçlanır ve dizin 3'teki alt liste hiçbir zaman döndürülemez. – Shar1er80

1

Listeleri birleştirme önceliklerinin soldan sağa olduğunu belirttiğinizden. Alt listelerin, istediğiniz miktara eşit veya daha az olacak şekilde birleştirilmesi için bir O (N^2) döngüsü yeterlidir.

public static void main(String[] args) throws Exception { 
    List<List<String>> someList = new ArrayList() {{ 
     add(new ArrayList() {{ 
      add("a1"); 
      add("a2"); 
     }}); 
     add(new ArrayList() {{ 
      add("b1"); 
     }}); 
     add(new ArrayList() {{ 
      add("c1"); 
      add("c2"); 
      add("c3"); 
     }}); 
     add(new ArrayList() {{ 
      add("d1"); 
     }}); 
    }}; 

    combine(someList, 4); 

    for(List<String> subList : someList) { 
     System.out.println(subList); 
    } 
} 

private static void combine(List<List<String>> someList, int combineAmount) { 
    for (int i = 0; i < someList.size(); i++) { 
     // Check if the current list already equals or exceeds the combineAmount 
     if (someList.get(i).size() >= combineAmount) { 
      continue; 
     } 

     // Add sublists to the current sublists until the size of the current 
     // sublist equals or exceeds the combineAmount 
     for (int j = i + 1; j < someList.size(); j++) { 
      if (someList.get(i).size() + someList.get(j).size() > combineAmount) { 
       continue; 
      } 
      someList.get(i).addAll(someList.get(j)); 
      someList.remove(j); 
      j--; 

      // Don't bother checking other sublists if the newly 
      // combined sublists equals or exceeds the combineAmount 
      if (someList.get(i).size() >= combineAmount) { 
       break; 
      } 
     } 
    } 
} 

Sonuçlar (combineAmount = 4):

[a1, a2, b1, d1] 
[c1, c2, c3] 

Sonuçlar (combineAmount = 2):

[a1, a2] 
[b1, d1] 
[c1, c2, c3] 

Sonuçlar (combineAmount = 6):

[a1, a2, b1, c1, c2, c3] 
[d1] 
1

Anladığım kadarıyla bir liste listesini toplam 5 dizine birleştirmek istiyorsunuz. Bunu yaparken ilk önce sol tarafa öncelik vermek istersiniz.

Bunu yapmak için oluşturduğum bir yöntem. Ben belirli bir örnek istemediğini biliyorum ama bir örnek ayrıca bu soru var yardım diğerleri kadar iyi anlamalarına yardımcı olacağını düşünüyor: Bu kod ile herhangi bir sorun varsa

private static List<String> getListOf(List<List<String>> someList, int size) { 
    List<List<String>> combine = new ArrayList<List<String>>(); 
    List<List<String>> combinePrev = new ArrayList<List<String>>(); 
    int value = 0; 
    int indexCloseValue = 0; 
    int indexClose; 
    for(int i = 0; i < someList.size(); i++){//Loops through the lists 
     value = someList.get(i).size(); 
     boolean[] indexAdded = new boolean[someList.size()];//Used to make sure to not add duplicates 
     indexAdded[i] = true; 
     combine.add(someList.get(i));//add current loop to the combine list. 
     do{//A loop to try to add values other than the one of index i to equal size. This loops multiple times because it may take more than two to equal size. 
      indexCloseValue = 0; 
      indexClose = -1; 
      for(int j = 0; j < someList.size(); j++){ 
       if(!indexAdded[j]){ 
        int listSize = someList.get(j).size(); 
        if(value + listSize > indexCloseValue && value + listSize <= size){ 
         indexCloseValue = listSize; 
         indexClose = j; 
        } 
       } 
      } 
      if(indexClose == -1){ 
       break; 
      }else{ 
       combine.add(someList.get(indexClose)); 
       value+=indexCloseValue; 
       indexAdded[indexClose] = true; 
      } 
     }while(value + indexCloseValue < size); 
     int added = 0; 
     for(List<String> str : combine){//Check size of combine list 
      added+=str.size(); 
     } 
     int addedPrev = 0; 
     for(List<String> str : combinePrev){//Check size of combinePrev list 
      addedPrev+=str.size(); 
     } 
     if(added > addedPrev && added <= size){ 
      combinePrev = new ArrayList<List<String>>(combine);//Set combinePrev to combine if it is larger but less than size 
     } 
     combine = new ArrayList<List<String>>();//Reset combine 
    } 

    List<String> returnList = new ArrayList<String>(); 
    for(List<String> list : combinePrev){//converts double list to a single list of strings at length "size". 
     for(String str : list){ 
      returnList.add(str); 
     } 
    } 
    return returnList;  
} 

veya bir sorum var yorumlarda bana sor.

İlgili konular