【问题标题】:How to shuffle consonants in a string?如何洗牌字符串中的辅音?
【发布时间】:2018-02-11 09:25:31
【问题描述】:

在 PHP 中,我们知道我们可以使用函数 str_shuffle() 随机打乱字符串字符。所以字符串"developer"每次都会变成"lrevdeope", "dvolpeere"等等。

但这不是我想要的。相反,我只想随机打乱辅音。所以"developer"应该在每次页面刷新时变成"verelodep", "leveroped"等。

我们怎样才能实现它?有什么想法吗?

【问题讨论】:

    标签: php shuffle


    【解决方案1】:

    几分钟后我得到了这个:

    $s = 'developer';
    $cons = [];
    for ($i = 0; $i < strlen($s); $i++) {
        if (!in_array($s[$i], ['a', 'e', 'i', 'o', 'u', 'y'])) {
            $cons[] = $s[$i];
            $s[$i] = '-';
        }
    }
    
    shuffle($cons);
    
    for ($i = 0; $i < strlen($s); $i++) {
        if ($s[$i] == '-') {
            $s[$i] = array_shift($cons);
        }
    }
    
    echo $s . PHP_EOL;
    

    【讨论】:

    • @u_mulder 请缓存strlen()。好答案。 strpos() 而不是 in_array() 呢?也许更快。
    • ...作为良好的角色建模,请在您的代码中包含一些解释。
    • @mickmackusa strlen 的复杂度为 O(1),无需缓存任何内容。我不认为strpos 会显着加快这段代码的速度。
    • 它有效,所以显然它是不需要。 “不要重复自己”/“不要让 php 重复函数调用”怎么样?
    【解决方案2】:

    这里有一个替代方案:

    $word = "developer";
    
    $letters = str_split($word);
    
    $consonants = array_filter($letters, function ($letter) {
        return !in_array($letter, ['a', 'e', 'i', 'o', 'u', 'y']);
    }); //Get all consonants with their index
    
    $consonantPositions = array_keys($consonants); //keep indexes (shuffle will lose them)
    
    shuffle($consonants);
    
    $letters = array_combine($consonantPositions, $consonants) + $letters; // put the shuffled consonants in their indexes and glue them back into the letters
    
    ksort($letters); // put the keys back in their place
    
    echo implode("",$letters); 
    

    【讨论】:

    • 我写了一个几乎相同的副本(没有发布 3v4l.org/oRkZA )。请实现array_diff() 而不是过滤器。 implode() 为空时不需要胶水参数。
    【解决方案3】:

    您可以像这样创建自定义函数:

    function shuffle_consonants($str) {
      $str = str_split($str);
      $vowels = ['a','e','i','o','u'];
    
      foreach($str as $char) 
          if(!in_array($char, $vowels)) $con .= $char;
    
      $con = str_shuffle($con);
      $idx = 0;
    
      foreach($str as &$char) 
          if(!in_array($char, $vowels)) $char = $con[$idx++];
    
      return implode("", $str);
    }
    echo shuffle_consonants("developer");
    

    【讨论】:

    • 将你的所有声明拼成一行并不能提高可读性。此外,仅代码答案在 StackOverflow 上的价值很低。
    • 由于缩进不佳且没有任何换行符,难以跟上!
    • 现在,请编辑您的答案,以教育未来的读者。
    • 你没有解释你的方法。请继续改进您的帖子。提供正确的方法只是 StackOverflow 上一篇好文章的开始。
    【解决方案4】:

    我很欣赏 u_mulder 方法的总体设计,但我想为任何可能感兴趣的读者做一些改进/微优化。

    • 存储strlen()值,这样php就不必重复生成它了。
    • 调用strpos() 来区分元音和辅音。 (参考:in_array vs strpos for performance in php

    • 不要暂时将输入字符串中的辅音替换为-

    • 仅迭代第二个循环中的辅音(而不是迭代字符串中的所有字母)。
    • 无需函数调用即可对字符串进行替换。

    代码:(Demo)

    $string="developer";
    $consonants=[];
    $length=strlen($string);
    for($offset=0; $offset<$length; ++$offset){  // iterate each letter of the string           ... OR for($offset=strlen($string); --$offset;){
        if(strpos('aeiou',$string[$offset])===false){  // isolate the consonants
            $consonants[]=$string[$offset];  // store the consonant
            $offsets[]=$offset;  // store the offset (aka indexed position of the consonant in the string)
        }
    }
    shuffle($consonants);  // shuffle the array of stored consonants
    
    foreach($consonants as $index=>$consonant){  // iterate ONLY the stored consonants
        $string[$offsets[$index]]=$consonant;  // reassign the consonants in their new positions
    }
    
    echo $string;  // possible output: revepoled
    

    这里是数组函数与 foreach 循环的混合,用于重新插入打乱的辅音:

    $string="developer";
    $consonants=array_diff(str_split($string),['a', 'e', 'i', 'o', 'u']);  // isolate consonants, preserve offsets as keys
    $offsets=array_keys($consonants); // store copy of offsets before shuffling
    shuffle($consonants);  // shuffle the array of stored consonants (returned value is re-indexed)
    
    foreach($consonants as $i=>$consonant){
        $string[$offsets[$i]]=$consonant;  // reassign the shuffled consonants at the known consonant positions
    }
    
    echo $string;
    

    对于那些认为我没有任何独立想法可提供的人...这是另一种方法,它将实现两个字符串函数调用,然后是一个正则表达式函数调用(这将对速度产生负面影响,但不会造成可怕的影响),这可能写成两行。

    代码:(Demo)

    $word="developer";
    
    $shuffled_consonants=str_shuffle(str_replace(['a','e','i','o','u'],'',$word));  // generate shuffled string of consonants
    
    // reinsert shuffled consonants at original consonant positions
    echo preg_replace_callback(
        '~[^aeiou]~',                                 // match each consonant at original position
        function($m)use($shuffled_consonants){        // pass in the shuffled string
            static $offset=0;                         // init the offset counter
            return $shuffled_consonants[$offset++];   // insert new consonant at original position using post-incrementation
        },
        $word);
    

    【讨论】:

      猜你喜欢
      • 2016-06-19
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2019-12-09
      • 1970-01-01
      • 2016-06-11
      • 2022-11-20
      • 2017-10-21
      相关资源
      最近更新 更多