字典<char,char =“”>用于映射字母 - 具有唯一键和&amp;值</炭,>

时间:2011-09-14 17:23:22

标签: c# collections random dictionary map

我需要创建一个表达字母表中每个字符与该字母表中另一个字符之间的映射的字典,其中键和值都是唯一的 - 就像一个表达如何编码/解码消息的非常简单的密码。不能有重复的键或值。

有人看到这段代码有什么问题吗?它仍然在映射中产生重复的值,尽管在​​每次迭代时,可用字符池对于已经使用的每个值都会减少。

        string source_alphabet = _alphabet; //ie "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        string target_alphabet = _alphabet;

        Dictionary<char, char> _map = new Dictionary<char, char>();

        for (int i = 0; i < source_alphabet.Length; i++)
        {
            int random = _random.Next(target_alphabet.Length - 1); //select a random index

            char _output = target_alphabet[random]  //get the char at the random index

            _map.Add(source_alphabet[i], _output); //add to the dictionary

            target_alphabet = target_alphabet.Replace(_output.ToString(), string.Empty); 
            // remove the char we just added from the remaining alphabet
        } 

感谢。

4 个答案:

答案 0 :(得分:1)

我会考虑对字母表中的一个或两个序列执行简单的Fisher Yates shuffle,然后您可以简单地迭代输出并将您的映射器放在一起。

伪代码

Shuffle(sequence1)
Shuffle(sequence2)

for index 0 to 25
    dictionary add sequence1[index], sequence2[index]

当您尝试每次选择随机值时,您很可能会发生碰撞,因此选择了非唯一值。答案通常是洗牌,然后按顺序选择。

答案 1 :(得分:1)

“快速修复”虽然不是最佳的(如果不允许将A映射到A)

 int random = _random.Next(target_alphabet.Length - 1);
 while ( source_alphabet[i] == target_alphabet[random] ) {random = _random.Next(target_alphabet.Length - 1);};

如果允许将A映射到A,则忽略上述更改...但至少将最后一行更改为

target_alphabet = target_alphabet.Remove ( random, 1 );

答案 2 :(得分:0)

我猜你可以在现有的“for”循环中的target_alphabet上添加另一个“for”循环,并检查字符与小“if”条件不相同,如果相同则继续内循环,否则继续内部循环。

答案 3 :(得分:0)

这很有效。

 for (int i = 0; i < source_alphabet.Length; i++)
    {
        int random = _random.Next(target_alphabet.Length - 1); //select a random index

        char _output = target_alphabet[random];  //get the char at the random index


        _map.Add(source_alphabet[i], _output); //add to the dictionary

        // remove the char we just added from the remaining alphabet
        target_alphabet = target_alphabet.Remove(random, 1);


    }