【问题标题】:How to make a random names list without repeat in PHP?如何在 PHP 中创建一个不重复的随机名称列表?
【发布时间】:2016-11-04 15:44:58
【问题描述】:

我的任务很简单——我得到一个名字列表:

约翰
玫瑰
戴夫

我需要按照以下规则为每个名称分配另外两个名称:

  1. 每个名字不能重复超过两次
  2. 子名 != 根名
  3. 根名称不能有相同的子名称。

意思是:

------ this is valid: --------------------------------------- this is not: -------

John - Rose, Dave  -------------------------------  John - Dave, Dave  
Rose - John, Jade    -------------------------------- Rose - Rose, Jade  
Dave - Jade, Rose    ------------------------------- Dave - Jade, John  
Jade - John, Dave   -------------------------------- Jade - John, Dave  

(dave's showing more than twice,
and John got him twice
and Rose got herself)

我已经尝试解决这个问题好几个小时了 - 为 subnames1 和 subnames2 分配名称很容易,但是当尝试将它们分配给根名称时,一切都变得一团糟。

这是我最近的失败:

$arr1 = $arr2 = $names = $arr;
        shuffle($arr1);
        shuffle($arr2);

        foreach ($arr1 as $key => $value) {
            $arr1[$key]['name2'] = $arr2[$key]['name'];
            $count = 0;
            foreach ($arr1 as $name) {
                if (in_array($arr2[$key]['name'], $name)) {
                    $count++;
                }
            }


            while ($arr1[$key]['name2'] == $arr1[$key]['name'] || $count > 2) {
                shuffle($arr2);
                $arr1[$key]['name2'] = $arr2[$key]['name'];
                foreach ($arr1 as $name) {
                    if (in_array($arr2[$key]['name'], $name)) {
                        $count++;
                    }
                }
            }
        }

        foreach ($names as $key => $name) {
            $randName = $names[array_rand($names)]['name'];
            while (in_array($randName, $arr1[$key]) || array_key_exists($randName, $arr1)) {
                $randName = $names[array_rand($names)]['name'];
            }
            $arr1[$randName] = $arr1[$key];
            unset($arr1[$key]);
        }

知道如何解决这个问题吗?

【问题讨论】:

  • 看看stackoverflow.com/a/10835795/4511585 和广告一些条件;)
  • Please tag your post titles | Don't
  • @PandaCool 无法从该代码中提取没有重复名称的随机结果...您知道这样做的条件是否足够好?

标签: php list loops random


【解决方案1】:

这个怎么样?

<?php
        $names = array("John","Rose","Dave","Jade");
        $pickedupOnce = array();
        $pickedupTwice = array();

        for($i=0; $i <count($names); $i++) {
            echo "$names[$i] <br/>";
            // this is rootname
            // now pick two random subnames

            $loop =0;
            do {
                $subOne = array_rand($names,1);
                $loop++;
            } while($subOne === $i || in_array($subOne, $pickedupTwice) && $loop<10 );

            if(in_array($subOne, $pickedupOnce)) {
                array_push($pickedupTwice, $subOne);
            }
            else {
                array_push($pickedupOnce, $subOne);
            }

            $loop = 0;
            do {
                $subTwo = array_rand($names,1);
                $loop++;

            } while($subTwo === $i || $subTwo === $subOne || in_array($subTwo, $pickedupTwice) && $loop<10 );

            if(in_array($subTwo, $pickedupOnce)) {
                array_push($pickedupTwice,$subTwo);
            }
            else {
                array_push($pickedupOnce, $subTwo);
            }

            echo "Group = $names[$i] -- $names[$subOne],$names[$subTwo] <br/>\n";
            echo "Picked Once - ";
            for($j=0; $j<count($pickedupOnce); $j++) {
                echo "$pickedupOnce[$j],";
            }

            echo "<br />Picked Twice - ";
            for($j=0; $j<count($pickedupTwice); $j++) {
                echo "$pickedupTwice[$j],";
            }
            echo "<br/>";
        }



        ?>

希望这会有所帮助...

【讨论】:

  • 这很好用! - 除了不时(我假设)while循环变得无限......知道为什么以及如何解决这个问题吗?在我的代码中有同样的问题 - 由于在最后一次迭代中缺少选项..
  • 编辑了解决无限循环的答案。它运行最大。 10次​​。所以有时确实会重复子名,尽管很少。
【解决方案2】:

我对PHP语法不熟悉,所以我会尝试一个伪代码实现,希望对你没问题

Input: nameList as string[].
Output: resultList as string[]

def secNames as string[]
    name1 as string
    name2 as string 

// make a list with two copies of all names 
for (i=0;i<length(nameList);i+1)
{ 
  secNames[i]=nameList[i]
  secNames[2*length(nameList)-i-1]=nameList[i]
}
// N.B.: first half of secondary names list is the same 
// as original, the second half is reversed so in your
// example we get: 
// "John","Rose","Dave","Jade","Jade","Dave","Rose","John"


// scan list of primary names 
for (i=0;i<length(nameList);i+1)
{
   resultList[i]=nameList[i]+" - "
   name1=""
   name2=""

   for (j=0;j<length(secNames);j+1) // scan secondary names
   {
     if (name1 <> secNames[j] and 
         name1 ="" and // skip this if found 1st sec.name 
         nameList[i] <> secNames[j]) // never pick main name
          {
            name1=secNames[j] // found first name
            secNames[j]="" // make this choice not  
                           // available on next pass
          }
       if (name2 <> secNames[j] and 
          name2 ="" and // skip this if found 2nd sec.name 
          nameList[i] <> secNames[j] and //never pick main 
          name1 <> secNames[j] // name is not used already 
          {                 
            name2=secNames[j])
            secNames[j]="" // remove choice for next pass
          }
    }
    if (name1="" or name2="")
    {
       //input does not allow for solution
       throw("Problem cannot be solved!!!") 
    }
    //assembly result
    resultList[i]=nameList[i]+name1+","+name2 

}

基本上,我们从名称列表中创建第二个列表,其中所有名称都重复(但第二个副本的顺序相反)。 我们扫描该列表以查找第一个和第二个选择,每次选择一个名称时,我们都会将其从次要名称列表中删除。 您的示例应该返回:

John - Rose,Dave
Rose - John,Jade
Dave - Jade,Rose
Jade - Dave,John

请注意,这并不是真正的“随机”——当使用相同的输入调用时,它总是会返回相同的列表,但它也会始终尝试满足您的要求。

【讨论】:

  • 嗯,也许我把它翻译错了,但我只是得到这个:约翰 - 约翰,约翰,约翰,约翰玫瑰 - 玫瑰,玫瑰,玫瑰,玫瑰戴夫 - 戴夫,戴夫.戴夫,戴夫玉 - 玉,玉,玉,玉
  • 对不起,Eliran - 编写伪代码使调试变得更加复杂 :( 我已经纠正了这个问题,现在应该会更好......
  • 修复工作完美!太糟糕了,这里不能暗示随机性质......虽然我可以随机化输入,因此创建一个“随机”结果:)
  • @EliranShemesh - 你可以试试这个:随机创建 secNames 列表,但将其实现为循环列表而不是数组并循环,直到找到你的两个候选人。只要您传递的输入不是“退化”(即少于 3 个名称,或类似“John”、“Rose”、“Dave”、“John”),这应该仍然有效。
  • 听起来很棒。我会实现这个
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-03
  • 1970-01-01
  • 2013-10-28
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多