【问题标题】:Get all combinations from 2D array从二维数组中获取所有组合
【发布时间】:2019-08-05 09:03:47
【问题描述】:

我有一个二维数组,我想获得所有可能的组合。但我被困在如何做到这一点上。我的数据数组如下所示:

var data = new string[][]
            {
                new string[] {"pa", "ga", "ka"},
                new string[] {"pb", "gb", "kb"}
            };

我的预期输出是这样的:

pa ga ka
pa ga kb
pa gb ka
pa gb kb
pb ga ka
pb ga kb
pb gb ka
pb gb kb

顺序也很重要。例如,我无法组合 ga pa ka。因为第一项需要以 p 开头,第二项以 g 开头,第三项以 k 开头。因此我不能使用笛卡尔积。

注意:在这个例子中,我有两行。我也有可能有更多行。

【问题讨论】:

  • 尤其是Eric Lippert's answer(如果您对所有血腥细节感兴趣,请阅读他提到的博客)。
  • 你确定它是重复的吗?在我的示例中,我只有两行来保持简单。但也有可能我有更多行。
  • 我很确定 - Eric 的答案包含 IEnumerable<IEnumerable<T>>,这意味着您可以将任意数量的数组传递给它。
  • 顺序对我来说也很重要。例如,对于 Eric 的回答,我从 var data = new string[][] { new string[] {"1", "2", "3"}, new string[] {"x", "y", " z"} }; var x = data.CartesianProduct(); 1y的组合。在我的情况下不能使用。

标签: c# combinations permutation


【解决方案1】:

可以使用 Eric Lippert 的解决方案,但您需要先转置您的输入。

这里是转置方法,written by u/recursive

public static IEnumerable<IEnumerable<T>> Transpose<T>(
    IEnumerable<IEnumerable<T>> @this)
{
    var enumerators = @this.Select(t => t.GetEnumerator())
       .Where(e => e.MoveNext());

    while (enumerators.Any())
    {
        yield return enumerators.Select(e => e.Current);
        enumerators = enumerators.Where(e => e.MoveNext());
    }
}

这是 Eric Lippert 的组合生成器,lifted from here

public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences)
{
    IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
    return sequences.Aggregate(
        emptyProduct,
        (accumulator, sequence) =>
            from accseq in accumulator
            from item in sequence
            select accseq.Concat(new[] { item })
    );
}

把它们放在一起:

static void Main()
{
    var data = new string[][]
    {
        new string[] {"pa", "ga", "ka"},
        new string[] {"pb", "gb", "kb"}
    };

    var transposed = Transpose(data);

    foreach (var comb in CartesianProduct(transposed))
    {
        Console.WriteLine(string.Join(", ", comb));
    }
}

由此产生的输出是:

pa, ga, ka
pa, ga, kb
pa, gb, ka
pa, gb, kb
pb, ga, ka
pb, ga, kb
pb, gb, ka
pb, gb, kb

这是您指定的要求。

【讨论】:

    【解决方案2】:
    var data = new string[][]
            {
                new string[] {"pa", "ga", "ka"},
                new string[] {"pb", "gb", "kb"}
            };
        foreach(var first in data[0])
        {
            foreach(var second in data[1])
            {
                List<string> list = new List<string>(data[1]);
                list.Remove(second);
                var arrayList=list.ToArray();
                string[] myArray = new string[3];
                myArray[0] = first;
                myArray[1] = arrayList[0];
                myArray[2] = arrayList[1];
                Console.WriteLine("{0}", string.Join(" ", myArray));            
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-30
      • 2022-01-25
      • 2019-04-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多