【问题标题】:Get random word of specific length from wordlist从单词列表中获取特定长度的随机单词
【发布时间】:2017-01-20 22:09:24
【问题描述】:

我正在编写一个简单的 PHP 函数,该函数将访问 word-list.txt 并拉出一个随机单词(单词由新行分隔)。该单词的最大长度必须为 $maxlength。按照我写的方式,它会拉出单词,如果长度太长,它会不断获取一个新单词,直到它小于或等于 $maxlength。我遇到的问题是脚本在最大执行时间内返回了一个致命错误。代码如下:

function GetWord($maxlength) {
    $file_content = file('word-list.txt');
    $nword = $file_content[array_rand($file_content)];

    while(mb_strlen($nword) > $maxlength) {
        $nword = $file_content[array_rand($file_content)];
    }

    return $nword;
}

我能想到的唯一替代方法是将单词表放入数据库中,并有一列包含每个对应单词的长度。这将允许我根据它们的长度选择单词选择。然而,我试图避免使用数据库,所以我想找出我的脚本有什么问题。任何帮助是极大的赞赏。谢谢!

【问题讨论】:

  • 我应该提到的是这个文件相当大,包含超过 9,000 行。这导致一些给定的建议仍然超时。

标签: php file random strlen word-list


【解决方案1】:

下面的类在实例化时会进行一些排序,但是每次查找随机单词只需要 O(1) 时间:

class RandomWord {
    private $words;
    private $boundaries;

    private static function sort($a, $b){
        return strlen($a) - strlen($b);
    }

    function __construct($file_name) {
        $this->words = file($file_name, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

        // Sort the words by their lenghts
        usort($this->words, array('RandomWord', 'sort'));

        // Mark the length boundaries
        $last = strlen($this->words[0]);

        foreach($this->words as $key => $word) {
            $length = strlen($word);

            if ($length > $last) {
                for($i = $last; $i < $length; $i++) {
                    // In case the lengths are not continuous
                    //    we need to mark the intermediate values as well
                    $this->boundaries[$i] = $key - 1;
                }
                $last = $length;
            }
        }
    }

    public function get($max_length) {
        if (isset($this->boundaries[$max_length])) {
            return $this->words[rand(0, $this->boundaries[$max_length])];
        }

        return $this->words[array_rand($this->words)];
    }
}

像这样使用它:

$r = new RandomWord("word-list.txt");
$word1 = $r->get(6);
$word2 = $r->get(3);
$word3 = $r->get(7);
...

更新:现在我已经对其进行了测试并且可以使用。

【讨论】:

    【解决方案2】:

    我认为问题来自于过于复杂的事情。

    你可以爆炸内容

    $content_array = explode("\n", $file_content);
    

    洗牌

    shuffle($content_array)
    

    然后搜索给定长度的第一个单词。

    foreach($content_array as $word) {
        if(strlen($word) == $word_length)
            return $word;
    }
    

    不过,我个人会将所有内容都放入数据库中。

    【讨论】:

      【解决方案3】:

      用随机索引重试确实是相当低效的。

      您可以按长度条件过滤行,这样就只剩下有效行,然后翻转这些行,使它们成为键。然后array_rand 可用于从中选择一个随机密钥。所有这些都可以通过函数式编程方式完成:

      function GetWord($maxlength) {
          return array_rand(array_flip(array_filter(file('word-list.txt'), 
              function($line) use ($maxlength) {
                  return mb_strlen($line) <= $maxlength;
              })));
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-17
        • 1970-01-01
        • 1970-01-01
        • 2012-12-03
        • 2013-06-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多