0

我正在大脑冻结,无法找到解决此问题的方法。

我创建了一个名为 CustomSet 的类,其中包含一个字符串列表。持有对 CustomSet 的引用的类将其存储为一个列表。

public class CustomSet : IEnumerable<string>
{
    public string Name { get; set; }
    internal IList<string> elements;

    public CustomSet(string name)
    {
        this.Name = name;
        this.elements = new List<string>();
    }

    public IEnumerable<string> Elements
    {
        get
        {
            return elements;
        }
    }
    public IEnumerator<string> GetEnumerator()
    {
        return elements.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

所以我想做的是遍历这个自定义集列表以输出一个二维字符串数组,其中列是 customSet 的数量,行是 customSet 元素的乘积。

例如,如果列表中有 3 个自定义集:第 1 个有 3 个元素,第 2 个有 2 个元素,第 3 个有 3 个元素。我想输出 3 列和 18 行 (3*2*3)。以下代码是解决方案的尝试:

CustomSet motion = new CustomSet("Motion");
motion.Elements.Add("low");
motion.Elements.Add("medium");
motion.Elements.Add("high");

CustomSet speed = new CustomSet("Speed");
speed.Elements.Add("slow");
speed.Elements.Add("Fast");

CustomSet mass = new CustomSet("Mass");
mass.Elements.Add("light");
mass.Elements.Add("medium");
mass.Elements.Add("heavy");

List<CustomSet> aSet = new List<CustomSet>();
aSet.Add(motion);
aSet.Add(speed);
aSet.Add(mass);

//problem code
int rows = 1;
for(int i = 0; i < aSet.Count; i++)
{
    rows *= aSet[i].Elements.Count;
}

string[,] array = new String[aSet.Count, rows];
int modulus;

for (int i = 0; i < aSet.Count; i++)
{
    for (int j = 0; j < rows; j++)
    {
        modulus = j % aSet[i].Elements.Count;
        array[i, j] = aSet[i].Elements[modulus];
    }
}

for (int j = 0; j < rows; j++)
{
    for (int i = 0; i < aSet.Count; i++)
    {
        Console.Write(array[i, j] + " / ");
    }
    Console.WriteLine();
}
//end

Console.ReadLine();

但是,代码不会输出正确的字符串数组(尽管它很接近)。我希望它输出的是以下内容:

低/慢/轻/

低/慢/中/

低/慢/重/

低/快/轻/

低/快/中/

低/快/重/

中/慢/轻/

中/慢/中/

中/慢/重/

中/快/轻/

中/快/中/

中/快/重/

高/慢/轻/

高/慢/中/

高/慢/重/

高/快/轻/

高/快/中/

高/快/重/

现在这个问题中的变量是列表中customSet的数量和每个CustomSet中的元素数量。

4

2 回答 2

7

您可以一次性获得产品:

var crossJoin = from m in motion
                from s in speed
                from ms in mass
                select new { Motion = m, Speed = s, Mass = ms };

foreach (var val in crossJoin)
{
   Console.Write("{0} / {1} / {2}", val.Motion, val.Speed, val.Mass);
}

现在,由于您不知道列表的数量,您需要做更多的事情。Eric Lippert 在本文中对此进行了介绍,您可以通过CertesianProduct以下方式使用其中定义的函数:

var cProduct = SomeContainerClass.CartesianProduct(aSet.Select(m => m.Elements));
var stringsToOutput = cProduct.Select(l => string.Join(" / ", l));
于 2013-08-08T16:12:42.723 回答
1

这种递归方法根据需要显示结果,其中包含 n 个 CustomSet 对象的列表:

void OutputSets(List<CustomSet> aSet, int setIndex, string hirarchyString)
{
    string ouputString = hirarchyString;
    int nextIndex = setIndex + 1;

    foreach (string element in aSet[setIndex].Elements)
    {
        if (nextIndex < aSet.Count)
        {
            OutputSets(aSet, nextIndex, hirarchyString + element + " / ");
        }
        else
        {
            Console.WriteLine(ouputString + element + " / ");
        }
    }
}

调用它:

OutputSets(aSet, 0, "");
于 2013-08-09T09:38:31.330 回答