2010-11-13 23 views
-1

J'ai une arraylist de chaînes "ABCDE" Je veux une méthode pour retourner une autre arraylist avec toute la combinaison possible d'une arraylist donnée (ex: ab, ac, ad ...) en C#comment obtenir toute la combinaison d'un arraylist?

quelqu'un sait une méthode simple?

NB: toutes les combinaisons possibles de longueur 2, et serait mieux si la longueur est variable (modifiable)

+0

Voulez-vous dire toutes les combinaisons de longueur = 2? –

+0

oui désolé oublié de mentionner – Mona

+0

toutes les combinaisons possibles de longueur 2 – Mona

Répondre

9

Qualifie votre commentaire nécessitant des combinaisons de deux longueurs:

string s = "abcde"; 
var combinations = from c in s 
        from d in s.Remove(s.IndexOf(c), 1) 
        select new string(new[] { c, d }); 
foreach (var combination in combinations) { 
    Console.WriteLine(combination); 
} 

répondre à votre modifier pour toute longueur:

static IEnumerable<string> GetCombinations(string s, int length) { 
    Guard.Against<ArgumentNullException>(s == null); 
    if (length > s.Length || length == 0) { 
     return new[] { String.Empty }; 
    if (length == 1) { 
     return s.Select(c => new string(new[] { c })); 
    } 
    return from c in s 
      from combination in GetCombinations(
       s.Remove(s.IndexOf(c), 1), 
       length - 1 
      ) 
      select c + combination; 
} 

Utilisation:

string s = "abcde"; 
var combinations = GetCombinations(s, 3); 
Console.WriteLine(String.Join(", ", combinations)); 

Sortie:

abc, abd, abe, acb, acd, ace, adb, adc, ade, aeb, aec, aed, bac, bad, bae, bca, 
bcd, bce, bda, bdc, bde, bea, bec, bed, cab, cad, cae, cba, cbd, cbe, cda, cdb, 
cde, cea, ceb, ced, dab, dac, dae, dba, dbc, dbe, dca, dcb, dce, dea, deb, dec, 
eab, eac, ead, eba, ebc, ebd, eca, ecb, ecd, eda, edb, edc 
+0

Aussi, vous devriez faire var retComb = GetCombinations (s, 2) .Distinct(). Où (p => p [0]> = p [p.Length]); pour supprimer les items redondants, et inverser des items, par exemple pour 'aabd' testez votre approche –

5

Voici ma fonction générique qui peut renvoyer toutes les combinaisons de type T:

static IEnumerable<IEnumerable<T>> GetCombinations<T>(IEnumerable<T> list, int length) 
{ 
    if (length == 1) return list.Select(t => new T[] { t }); 

    return GetCombinations(list, length - 1) 
     .SelectMany(t => list, (t1, t2) => t1.Concat(new T[] { t2 })); 
} 

Utilisation:

Console.WriteLine(
    string.Join(", ", 
     GetCombinations("abcde".ToCharArray(), 2).Select(list => string.Join("", list)) 
    ) 
); 

Sortie:

aa, ab, ac, ad, ae, ba, bb, bc, bd, be, ca, cb, cc, cd, ce, da, db, dc, dd, de, ea, eb, ec, ed, ee 

MISE À JOUR Veuillez consulter ma réponse here pour d'autres scénarios, par ex. permutations et k-combinaisons, etc.

+0

C'est permutation avec répétition et non combinaison. http://www.mathsisfun.com/combinatorics/combinations-permutations.html –

+0

@ HalilKaskavalci, s'il vous plaît vérifier [une autre réponse à moi] (http://stackoverflow.com/a/10629938/1251423) pour plus d'options. – Pengyang

+0

Cela semble beaucoup mieux maintenant. –

-1

combinaison de chiffres en tableau en utilisant des tableaux seulement et récursion:

static int n = 4; 
    int[] baseArr = { 1, 2, 3, 4 }; 
    int[] LockNums; 

    static void Main(string[] args) 
    { 
     int len = baseArr.Length; 
     LockNums = new int[n]; 

     for (int i = 0; i < n; i++) 
     { 
      int num = baseArr[i]; 
      DoCombinations(num, baseArr, len); 
      //for more than 4 numbers the print screen is too long if we need to check the result next line will help 
      //Console.ReadLine(); 

     } 
    } 

    private void DoCombinations(int lockNum, int[] arr, int arrLen)   
    { 
     int n1 = arr.Length; 
     // next line shows the difference in length between the previous and its previous array 
     int point = arrLen - n1; 
     LockNums[n - arr.Length] = lockNum; 

     int[] tempArr = new int[arr.Length - 1]; 
     FillTempArr(lockNum, arr, tempArr); 

     //next condition will print the last number from the current combination 
     if (arr.Length == 1) 
     { 
      Console.Write(" {0}", lockNum); 
      Console.WriteLine(); 
     } 

     for (int i = 0; i < tempArr.Length; i++) 
     { 
      if ((point == 1) && (i != 0)) 
      { 
       //without this code the program will fail to print the leading number of the next combination 
       //and 'point' is the exact moment when this code has to be executed 
       PrintFirstNums(baseArr.Length - n1); 
      } 
      Console.Write(" {0}", lockNum); 
      int num1 = tempArr[i]; 
      DoCombinations(num1, tempArr, n1); 
     } 
    } 

    private void PrintFirstNums(int missNums) 
    { 
     for (int i = 0; i < missNums; i++) 
     { 
      Console.Write(" {0}", LockNums[i]); 
     } 
    } 

    private void FillTempArr(int lockN, int[] arr, int[] tempArr) 
    { 
     int idx = 0; 
     foreach (int number in arr) 
     { 
      if (number != lockN) 
      { 
       tempArr[idx++] = number; 
      } 
     } 
    } 

    private void PrintResult(int[] arr) 
    { 
     foreach (int num in arr) 
     { 
      Console.Write(" {0}", num); 
     } 
    } 
+0

Bonjour, ceci est ma solution pour une combinaison de nombres. La solution utilise uniquement des tableaux. Je fais ce post parce que je n'ai pas rencontré une solution avec des tableaux partout. Le code est défini pour une démonstration rapide, sinon il devrait fonctionner avec n'importe quelle longueur de tableau. –