简体   繁体   English

遍历数组的所有可能组合

[英]Loop Through Every Possible Combination of an Array

I am attempting to loop through every combination of an array in C# dependent on size, but not order. 我通过在C#依赖于规模,而不是为了一个阵列的每个组合试图循环。 For example: var states = ["NJ", "AK", "NY"]; 例如: var states = ["NJ", "AK", "NY"];

Some Combinations might be: 一些组合可能是:

states = [];
states = ["NJ"];
states = ["NJ","NY"];
states = ["NY"];
states = ["NJ", "NY", "AK"];

and so on... It is also true in my case that states = ["NJ","NY"] and states = ["NY","NJ"] are the same thing, as order does not matter. 依此类推...在我的情况下, states = ["NJ","NY"]states = ["NY","NJ"]也是同一件事,因为顺序无关紧要。

Does anyone have any idea on the most efficient way to do this? 有没有人对最有效的方式任何想法做到这一点?

The combination of the following two methods should do what you want. 以下两种方法的组合应该可以实现您想要的。 The idea is that if the number of items is n then the number of subsets is 2^n. 这个想法是,如果项数为n,则子集数为2 ^ n。 And if you iterate from 0 to 2^n - 1 and look at the numbers in binary you'll have one digit for each item and if the digit is 1 then you include the item, and if it is 0 you don't. 并且,如果您从0迭代到2 ^ n-1并查看二进制数,则每个项目都有一个数字,如果数字为1,则包含该项目,如果为0,则不包含该项目。 I'm using BigInteger here as int would only work for a collection of less than 32 items and long would only work for less than 64. 我在这里使用BigInteger ,因为int仅适用于少于32个项目的集合,而long仅适用于少于64个项目的集合。

public static IEnumerable<IEnumerable<T>> PowerSets<T>(this IList<T> set)
{
    var totalSets = BigInteger.Pow(2, set.Count);
    for (BigInteger i = 0; i < totalSets; i++)
    {
        yield return set.SubSet(i);
    }
}

public static IEnumerable<T> SubSet<T>(this IList<T> set, BigInteger n)
{
    for (int i = 0; i < set.Count && n > 0; i++)
    {
        if ((n & 1) == 1)
        {
            yield return set[i];
        }

        n = n >> 1;
    }
}

With that the following code 有了下面的代码

var states = new[] { "NJ", "AK", "NY" };

foreach (var subset in states.PowerSets())
{
    Console.WriteLine("[" + string.Join(",", subset.Select(s => "'" + s + "'")) + "]");
}

Will give you this output. 会给你这个输出。

[]
['NJ']
['AK']
['NJ','AK']
['NY']
['NJ','NY']
['AK','NY']
['NJ','AK','NY']

You can use back-tracking where in each iteration you'll either (1) take the item in index i or (2) do not take the item in index i. 您可以使用回溯,在每次迭代中,您要么(1)取得索引i中的项目,要么(2)不取得索引i中的项目。

Pseudo code for this problem: 此问题的伪代码:

Main code: 主要代码:

  • Define a bool array (eg named picked ) of the length of states 定义states长度的布尔数组(例如,命名为picked
  • Call the backtracking method with index 0 (the first item) 调用索引为0的回溯方法(第一项)

Backtracking function: 回溯功能:

  • Receives the states array, its length, the current index and the bool array 接收states数组,其长度,当前索引和布尔数组
  • Halt condition - if the current index is equal to the length then you just need to iterate over the bool array and for each item which is true print the matching string from states 暂停条件-如果当前索引等于长度,则只需要遍历bool数组,对于每个为true的项目,从states打印匹配的字符串
  • Actual backtracking: 实际回溯:
    • Set picked[i] to true and call the backtracking function with the next index picked[i]设置为true并使用下一个索引调用回溯功能
    • Set picked[i] to false and call the backtracking function with the next index picked[i]设置为false并使用下一个索引调用回溯功能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM