c# - 在 C# 中生成 List<List<KeyPairValue<string, string>>> 子集的排列

标签 c# list permutation

请看下面的示例代码:

List<List<KeyValuePair<string, string>>> list = new List<List<KeyValuePair<string, string>>>();

list.Add(new List<KeyValuePair<string, string>>());
list[0].Add(new KeyValuePair<string, string>("Category 1", "Value A"));
list[0].Add(new KeyValuePair<string, string>("Category 1", "Value B"));

list.Add(new List<KeyValuePair<string, string>>());
list[1].Add(new KeyValuePair<string, string>("Category 2", "Value C"));
list[1].Add(new KeyValuePair<string, string>("Category 2", "Value D"));

list.Add(new List<KeyValuePair<string, string>>());
list[2].Add(new KeyValuePair<string, string>("Category 3", "Value E"));

也可以表示为:

+---------------------------+---------------------------+
| ["Category 1", "Value A"] | ["Category 1", "Value B"] |
+---------------------------+---------------------------+
| ["Category 2", "Value C"] | ["Category 2", "Value D"] |
+---------------------------+---------------------------+
| ["Category 3", "Value E"] |                           |
+---------------------------+---------------------------+

我需要以每列包含一个唯一类别的方式重新排列这些值,并且我必须 copy-and-swap 值,以便在给定类别限制的情况下实现所有可能的值排列。换句话说...

+---------------------------+---------------------------+---------------------------+
| ["Category 1", "Value A"] | ["Category 2", "Value C"] | ["Category 3", "Value E"] |
+---------------------------+---------------------------+---------------------------+
| ["Category 1", "Value B"] | ["Category 2", "Value D"] | ["Category 3", "Value E"] |
+---------------------------+---------------------------+---------------------------+
| ["Category 1", "Value B"] | ["Category 2", "Value C"] | ["Category 3", "Value E"] |
+---------------------------+---------------------------+---------------------------+
| ["Category 1", "Value A"] | ["Category 2", "Value D"] | ["Category 3", "Value E"] |
+---------------------------+---------------------------+---------------------------+

请注意,我交换了第一列中的第三个和第四个值,以获得唯一的行。在考虑我的问题时,请忽略使用哪一列,只要我最终得到此特定列/类别顺序中的唯一行,交换哪些值并不重要。另外,就像我之前所说的,这只是一个示例,我需要一些无论元素数量多少都可以工作的东西。

这是我到目前为止所拥有的(这里的变量列表与上面相同):

int elementAmount = list.Count;
int combinationAmount = list.Select(x => x.Count).Aggregate(1, (x, y) => x * y); //Multiply sublists element count

List<List<KeyValuePair<string, string>>> sortedList = new List<List<KeyValuePair<string, string>>>(combinationAmount);

for (int i = 0; i < combinationAmount; i++)
sortedList.Add(new List<KeyValuePair<string, string>>(elementAmount));

for (int j = 0; j < elementAmount; j++)
{
    for (int i = 0; i < combinationAmount; i++)
        sortedList[i].Add(list[j].Count > i ? list[j][i] : sortedList[i - list[j].Count][j]);
}

输出:

+---------------------------+---------------------------+---------------------------+
| ["Category 1", "Value A"] | ["Category 2", "Value C"] | ["Category 3", "Value E"] |
+---------------------------+---------------------------+---------------------------+
| ["Category 1", "Value B"] | ["Category 2", "Value D"] | ["Category 3", "Value E"] |
+---------------------------+---------------------------+---------------------------+
| ["Category 1", "Value A"] | ["Category 2", "Value C"] | ["Category 3", "Value E"] |
+---------------------------+---------------------------+---------------------------+
| ["Category 1", "Value B"] | ["Category 2", "Value D"] | ["Category 3", "Value E"] |
+---------------------------+---------------------------+---------------------------+

如果我想出了一个误导性的标题,我很抱歉,用一行来概括整个问题有点困难。请根据您的喜好进行编辑。

编辑:我只是缺少交换。

最佳答案

首先回答问题。请注意,之后我将发布一些不会被数据结构混淆的内容,仅通过递归显示排列。

    private void button1_Click(object sender, EventArgs e)
    {
        List<List<KeyValuePair<string, string>>> list = new List<List<KeyValuePair<string, string>>>();

        list.Add(new List<KeyValuePair<string, string>>());
        list[0].Add(new KeyValuePair<string, string>("Category 1", "Value A"));
        list[0].Add(new KeyValuePair<string, string>("Category 1", "Value B"));

        list.Add(new List<KeyValuePair<string, string>>());
        list[1].Add(new KeyValuePair<string, string>("Category 2", "Value C"));
        list[1].Add(new KeyValuePair<string, string>("Category 2", "Value D"));

        list.Add(new List<KeyValuePair<string, string>>());
        list[2].Add(new KeyValuePair<string, string>("Category 3", "Value E"));

        List<List<KeyValuePair<string, string>>> sortedList = new List<List<KeyValuePair<string, string>>>();

        permutation(list, 0, new List<KeyValuePair<string, string>>());
    }


    private void permutation( List<List<KeyValuePair<string, string>>> options, int srcPos, List<KeyValuePair<string, string>> result)
    {
        if (result.Count == options.Count)
            WriteOne(result);
        else
        {
            foreach (KeyValuePair<string, string> opt in options[srcPos])
            {
                List<KeyValuePair<string, string>> theClone = new List<KeyValuePair<string, string>>(result); 
                theClone.Add(opt); 
                permutation(options, srcPos + 1, theClone);
            }
        }
    }

    private void WriteOne(List<KeyValuePair<string, string>> OneResult)
    {
        StringBuilder line = new StringBuilder(80);
        StringBuilder line2 = new StringBuilder(80);
        line.Append("|"); line2.Append("+");
        foreach (KeyValuePair<string, string> item in OneResult)
        {
            line.Append(" [");       line2.Append("--");
            line.Append(item.Key);   line2.Append(new string('-', item.Key.Length));
            line.Append(", ");       line2.Append("--");
            line.Append(item.Value); line2.Append(new string('-', item.Value.Length));
            line.Append("] |");     line2.Append("--+");
        }
        line.AppendLine(); line2.AppendLine();
        Console.WriteLine(line.ToString());
        Console.WriteLine(line2.ToString());
    }

现在更简单的事情就是产生上面的事情。这是完全相同的算法,但通用列表符号不会使它变得困惑。

    private void Test()
    {
        permutation(new string[] { "AB", "CD", "E" }, 0, "");
    }


    private void permutation(string[] options, int srcPos, string result)
    {
        if (result.Length == options.Length)
            Console.WriteLine(result);
        else
        {
            foreach (char opt in options[srcPos])
            {
                permutation(options, srcPos + 1, result + opt);
            }
        }
    }

关于c# - 在 C# 中生成 List<List<KeyPairValue<string, string>>> 子集的排列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28635293/

相关文章:

c# - 尝试使用 TextRenderer.DrawText 将透明文本添加到位图图像

c# - C# 中的 Winsock 服务器/客户端应用程序

python - 找到固定长度数字的所有可能排列以达到给定的总和

c# - 我可以而且应该将修改字节数组的委托(delegate)转换为 Lambda 表达式吗?

c# - 为一个 Windows 用户生成唯一 key

python - 在Python中使用数组以更方便的方式编写长switch语句

java - java中允许remove()方法工作的Iteration的内部实现是什么?

python - 初始化pandas列表中的元素

algorithm - 计算一个循环中的排列数

Python - 新的遗漏排列列表