【问题标题】:Creating a random name generator. How do I accomplish this?创建一个随机名称生成器。我该如何做到这一点?
【发布时间】:2011-07-19 05:04:06
【问题描述】:

我正在尝试从此处的每个列表中获取一个项目,并将它们组合成一个唯一的名称。这只是为了踢球。 :)

以下是列表:

List<string> FirstNames = new List<string>()
{
    "Sergio",
    "Daniel",
    "Carolina",
    "David",
    "Reina",
    "Saul",
    "Bernard",
    "Danny",
    "Dimas",
    "Yuri",
    "Ivan",
    "Laura"
};

List<string> LastNamesA = new List<string>()
{
    "Tapia",
    "Gutierrez",
    "Rueda",
    "Galviz",
    "Yuli",
    "Rivera",
    "Mamami",
    "Saucedo",
    "Dominguez",
    "Escobar",
    "Martin",
    "Crespo"
};

List<string> LastNamesB = new List<string>()
{
    "Johnson",
    "Williams",
    "Jones",
    "Brown",
    "David",
    "Miller",
    "Wilson",
    "Anderson",
    "Thomas",
    "Jackson",
    "White",
    "Robinson"
};

我知道我通过索引获取单个项目,我也知道我可以使用 Random 类生成一个从 0 到 ListFoo.Count 的随机数。

我不知道如何检查是否已经从集合中提取了随机排列。

我考虑过使用元组类:

List<Tuple<int,int,int>> permutations = new List<Tuple<int,int,int>>();

但我在这里有一个脑残。 ;) 任何指导?我并不是真的在寻找这个简单问题的整个代码,只是一个建议或提示。


编辑

感谢这里给出的建议,这是我想出的。有改进的余地吗?

static void Main(string[] args)
{
    List<string> FirstNames = new List<string>()
    {
        "Sergio",
        "Daniel",
        "Carolina",
        "David",
        "Reina",
        "Saul",
        "Bernard",
        "Danny",
        "Dimas",
        "Yuri",
        "Ivan",
        "Laura"
    };

    List<string> LastNamesA = new List<string>()
    {
        "Tapia",
        "Gutierrez",
        "Rueda",
        "Galviz",
        "Yuli",
        "Rivera",
        "Mamami",
        "Saucedo",
        "Dominguez",
        "Escobar",
        "Martin",
        "Crespo"
    };

    List<string> LastNamesB = new List<string>()
    {
        "Johnson",
        "Williams",
        "Jones",
        "Brown",
        "David",
        "Miller",
        "Wilson",
        "Anderson",
        "Thomas",
        "Jackson",
        "White",
        "Robinson"
    };

    var permutations = new List<Tuple<int, int, int>>();
    List<string> generatedNames = new List<string>();

    Random random = new Random();
    int a, b, c;

    //We want to generate 500 names.
    while (permutations.Count < 500)
    {
        a = random.Next(0, FirstNames.Count);
        b = random.Next(0, FirstNames.Count);
        c = random.Next(0, FirstNames.Count);

        Tuple<int, int, int> tuple = new Tuple<int, int, int>(a, b, c);

        if (!permutations.Contains(tuple))
        {
            permutations.Add(tuple);
        }
    }

    foreach (var tuple in permutations)
    {
        generatedNames.Add(string.Format("{0} {1} {2}", FirstNames[tuple.Item1], 
                                                        LastNamesA[tuple.Item2],
                                                        LastNamesB[tuple.Item3])
        );
    }

    foreach (var n in generatedNames)
    {
        Console.WriteLine(n);
    }

    Console.ReadKey();
}

【问题讨论】:

  • 如果你开始排除对,它不再是随机的,不是吗?除非重复是一个明确的失败......如果没有绝对需要排除重复......让他们。
  • 有必要不要让相同的排列存在。它们必须是唯一的名称。由于它是 12 x 12 x 12,我可以获得 1600 多个唯一名称,不是吗?除非我的数学是关闭的。
  • @sergio Tapia,这是正确的 1728 种独特的可能性。你打算生成所有这些吗?还是只有几个?
  • @MerickOWA:我决定只生成 500 个。如果我要生成所有内容,我可以一个一个迭代并获得所有这些。真的不是很好的运动。 :)

标签: c# list random tuples


【解决方案1】:
  1. 创建一个包含 3 个随机数字的新元组
  2. 检查排列是否包含您的新元组
  3. 如果不是 => 将新元组添加到列表中。如果是,请再次从第 1 点开始。

【讨论】:

    【解决方案2】:

    使用 LINQ 生成它们真的很容易:

    var combs =
    (from first in FirstNames
    from second in LastNamesA
    from third in LastNamesB
    select new Tuple<string, string, string>(first, second, third)).ToList();
    

    在此之后,如果您需要从列表中随机取出唯一元素,只需将列表打乱,然后按顺序逐一挑选即可。

    您可以使用 Knuth-Fisher-Yates 算法(即就地洗牌):

    Random rand = new Random();
    
    for (int i = combs.Count - 1; i > 0; i--)
    {
        int n = rand.Next(i + 1);
        var mem = combs[i];
        combs[i] = combs[n];
        combs[n] = mem;
    }
    

    【讨论】:

      【解决方案3】:

      我会创建一个HashSet&lt;int&gt; 并存储选择的数字表示(例如,135 表示第一、第三和第五或使用 010305),然后检查它们是否在集合中。

      【讨论】:

        【解决方案4】:

        你在正确的轨道上! 每次生成名称时,将其添加到元组列表中

        //Create the tuple
        Tuple <int, int, int> tuple = new Tuple<int, int, int>(index1, index2, index3)
        
        if(!permutations.Contains(tuple))
        { 
            permutations.Add(tuple);
            //Do something else
        }
        

        【讨论】:

        • 这听起来很棒。我也在假设 Tuple 中的排列,对吗?
        【解决方案5】:

        HashSet 答案的另一种选择是提前构建所有可能的组合,将它们打乱,然后将它们存储在队列中,您可以在其中一次检索它们。这将避免每次构建新的时都必须检查现有的,并且仍然是随机的。

        这仅适用于您一开始没有大量数据集的情况,因为创建完整列表和洗牌所涉及的工作对于大量数据而言将是巨大的。

        【讨论】:

          【解决方案6】:

          我认为最简单的解决方案是将组合名称放入 HashSet&lt;string&gt; 中,这将确保创建的名称列表是唯一的。

          【讨论】:

          • 您认为HashSet&lt;int&gt;(其中 int 是用于索引数组的随机数的表示)可能会比HashSet&lt;string&gt; 带来性能提升吗?
          • @Hogan:对于这么小的结果集,我无法想象字符串和整数之间的性能差异。在我看来,为了保证你的算法,额外的微秒是值得的。例如,在您的回答中,{1,3,5} 的 010305 表示如果条目超过 100 个,代码将中断。我能看到保证成功的唯一方法是使用字符串或元组(或类似的类或结构)。我不知道是否可以使用int 作为您的密钥并使其通用。
          • 不过你不需要检查它,只要它们被选中就删除它们。
          • @Hogan - 如果您尝试构建的是唯一的名称列表,Hashset&lt;string&gt; 的优势在于无需额外的包含检查即可提供您需要的最终输出。
          • 是的。 @JonB:这需要首先生成所有可能的组合——这非常昂贵。
          猜你喜欢
          • 1970-01-01
          • 2011-02-18
          • 2017-02-19
          • 2018-07-25
          • 1970-01-01
          • 2013-01-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多