2012-07-13 41 views
1

如何從List<string>源生成長達一定長度的單詞的所有組合列表?從列表<string>生成所有組合的最大X長度

例如,我有一個List<string>的10600多個單詞,我需要將其轉換爲List<List<string>>,但是,子列表只需包含組合,直到幷包含給定的最大長度,對於此示例,我將說3.

我不關心的單詞出現在子列表中的順序。例如,我只需要列表中的以下一項:

"laptop", "computer", "reviews" 
"laptop", "reviews", "computer" 
"computer", "laptop", "reviews" 
"computer" "reviews", "laptop" 
"reviews", "computer", "laptop" 
"reviews", "laptop", "computer" 

這是否有可能是因爲我需要生成大量的組合?

任何幫助,非常感謝。

+0

使用C#遞歸 – BumbleB2na 2012-07-13 16:22:16

+0

所以從長度爲3的是列表中的每個不同的組合?是不是1.98446490×10^11組合(我還沒有計算長度1和2的長度,你想要的是它的聲音)。 – Bridge 2012-07-13 16:22:52

+0

你打算如何處理最終名單? – user845279 2012-07-13 16:27:00

回答

6

首先,我我不確定你是否真的想生成這麼龐大的名單。如果你真的這樣做,那麼我建議你考慮使用iterators懶惰列表生成,而不是這個龐大的名單:

static void Main() 
{ 
    var words = new List<string> {"w1", "w2", "w3", "w4", "w5", "w6", "w7"}; 

    foreach (var list in Generate(words, 3)) 
    { 
     Console.WriteLine(string.Join(", ", list)); 
    } 
} 

static IEnumerable<List<string>> Generate(List<string> words, int length, int ix = 0, int[] indexes = null) 
{ 
    indexes = indexes ?? Enumerable.Range(0, length).ToArray(); 

    if (ix > 0) 
     yield return indexes.Take(ix).Select(x => words[x]).ToList(); 

    if (ix > length) 
     yield break; 

    if (ix == length) 
    { 
     yield return indexes.Select(x => words[x]).ToList(); 
    } 
    else 
    { 
     for (int jx = ix > 0 ? indexes[ix-1]+1 : 0; jx < words.Count; jx++) 
     { 
      indexes[ix] = jx; 
      foreach (var list in Generate(words, length, ix + 1, indexes)) 
       yield return list; 
     } 
    } 
} 
+0

感謝您的迴應,它似乎運作良好。測試3個詞(「筆記本電腦」,「電腦」,「評論」),它給了我第二次發生的「筆記本電腦評論」。刪除'if(ix == length)'語句後,它工作正常。謝謝! – 2012-07-14 11:51:48

0

希望我沒有惹什麼。

for(int i = 0; i < list.Count; i ++) 
{ 
    list1 = new List<string> { list[i] }; 
    listcombinations.Add(list1); 
    for(int j = i + 1; j < list.Count; j ++) 
    { 
    list1 = new List<string> { list[i], list[j] }; 
    listcombinations.Add(list1); 
    for(int k = j + 1; k < list.Count; k ++) 
    { 
     list1 = new List<string> { list[i], list[j], list[k] }; 
     listcombinations.Add(list1); 
    } 
    } 
} 
+0

這隻適用於長度爲3的列表。但這只是原始問題中的一個示例。如果您需要製作10個元素的列表呢?這樣的解決方案看起來很古怪。 – 2012-07-13 16:52:32

+0

@OleksandrPshenychnyy原來的問題沒有提到「例如」,之後進行了編輯。對於這種情況,我的解決方案很簡單,易於理解,並且沒有任何性能開銷。無論如何,將它轉換爲使用遞歸是非常微不足道的。 – 2012-07-13 21:14:37

0

我想問題主要是檢查單詞的組合列表中已經存在:

您可以爲做什麼:

//generate a dictionary with key hashcode/value list of string 
Dictionary<int, List<string>> validCombinations= new Dictionary<int, List<string>>(); 

//generating anyway your combinations (looping through the words) 
List<string> combinationToCheck = new List<string>(){"reviews", "laptop", "computer"}; 

//sort the words 
combinationToCheck.Sort(); 
string combined = String.Join("", combinationToCheck.ToArray()); 

//calculate a hash 
int hashCode = combined.GetHashCode(); 

//add the combination if the same hash doesnt exist yet 
if(!validCombinations.ContainsKey(hashCode)) 
    validCombinations.Add(hashCode, combinationToCheck); 
0
private List<List<string>> GetCombinations() 
{ 

    List<List<string>> mResult= new List<List<string>>(); 

    for (int i = 0; i < mList.Count; i++) 
    { 
     for (int k = 0; k < mList.Count; k++) 
     { 
      if (i == k) continue; 

      List<string> tmpList = new List<string>(); 

      tmpList.Add(mList[i]); 
      int mCount = 1; 
      int j = k; 
      while (true) 
      { 

       if (j >= mList.Count) j = 0; 
       if (i != j) 
       { 

        tmpList.Add(mList[j]); 
        mCount++; 
       } 
       j += 1; 
       if (mCount >= mList.Count) break; 
      } 

      mResult.Add(tmpList); 
     } 

    } 
    return mResult; 
}