2

请考虑以下代码:

List<string> a = new List<string>(new string[] { "a1", "a2" });
List<string> b = new List<string>(new string[] { "b1", "b2" });
List<string> c = new List<string>(new string[] { "c1", "c2" });
List<List<string>> input = new List<List<string>>();
input.Add(a);
input.Add(b);
input.Add(c);
List<List<string>> output=List<List<string>> PickOneFromEachSet(input)

PickOneFromEachSet将从每个集合中选择一个元素而不考虑排序。

我们可以有 2^3=8 种组合,即输出为

{"a1","b1","c1"},
{"a1","b1","c2"},
...
{"a2","b2","c2"}

我们应该如何构造这样的函数?

4

4 回答 4

6

如果总是有三组,那很容易:

var query = from aValue in a
            from bValue in b
            from cValue in c
            select new List<string> { aValue, bValue, cValue };
List<List<string>> output = query.ToList();
于 2012-07-23T12:06:50.953 回答
3

请参阅使用 LINQ 计算笛卡尔积

List<string> a = new List<string>(new string[] { "a1", "a2" });
List<string> b = new List<string>(new string[] { "b1", "b2" });
List<string> c = new List<string>(new string[] { "c1", "c2" });

var result = CartesianProduct(new List<List<string>>(){a,b,c});

foreach (var row in result)
{
    foreach (var item in row)
    {
        Console.Write(item + " ");
    }
    Console.WriteLine();
}

//https://svn.apache.org/repos/asf/incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/contrib/SimpleFacetedSearch/Extensions.cs
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences)
{
    IEnumerable<IEnumerable<T>> emptyProduct = new IEnumerable<T>[] { Enumerable.Empty<T>() };
    return sequences.Aggregate(
        emptyProduct,
        (accumulator, sequence) =>
        {
            return accumulator.SelectMany(
                (accseq => sequence),
                (accseq, item) => accseq.Concat(new T[] { item })
            );
        }
    );
}

.NET 3.5

public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<List<T>> sequences)
{
    //SAME
}

输出:

a1 b1 c1
a1 b1 c2
a1 b2 c1
a1 b2 c2
a2 b1 c1
a2 b1 c2
a2 b2 c1
a2 b2 c2
于 2012-07-23T12:49:26.707 回答
1

这样的事情怎么样?

public List<T> GetFirstOfEach<T>(params List<T>[] Lists)
{
    List<T> rt = new List<T>();
    Lists.ToList().ForEach(l => rt.Add(l.First()));

    return rt;
}

这将允许您将任意数量的列表传递给函数。

List<string> output = GetFirstOfEach(a, b, c);
于 2012-07-23T12:07:57.180 回答
0

我改用了这段代码,我把它贴在这里作为替代:

List<string> a = new List<string>(new string[] { "a1", "a2" });
List<string> b = new List<string>(new string[] { "b1", "b2" });
List<string> c = new List<string>(new string[] { "c1", "c2" });

var result = CartesianProduct(new List<List<string>>(){a,b,c});

foreach (var row in result)
{
    foreach (var item in row)
    {
        Console.Write(item + " ");
    }
    Console.WriteLine();
}

     public static List<List<T>> CartesianProduct<T>(List<List<T>> sets)
            {              
                List<List<T>> results = new List<List<T>>();

                int solutions = 1;
                for (int i = 0; i < sets.Count; i++)
                {
                    solutions *= sets[i].Count;
                }
                for (int i = 0; i < solutions; i++)
                {
                    int j = 1;
                    List<T> elem = new List<T>();
                    foreach (List<T> set in sets)
                    {
                        elem.Add(set[(i / j) % set.Count]);
                        j *= set.Count;
                    }
                    results.Add(elem);
                }
                return results;
            }

输出:

a1 b1 c1
a1 b1 c2
a1 b2 c1
a1 b2 c2
a2 b1 c1
a2 b1 c2
a2 b2 c1
a2 b2 c2
于 2012-07-24T01:35:19.030 回答