代码之家  ›  专栏  ›  技术社区  ›  user7441072

如何检查是否可以从字母列表中创建单词?

  •  6
  • user7441072  · 技术社区  · 9 年前

    我有一根绳子 $raw="aabbcdfghmnejaachto" 和一个数组 $word_array=array('cat','rat','goat','total','egg') .

    我的程序需要检查是否可以用字符串中的字母生成数组中的单词。还有一个附加条件;如果单词包含一个出现多次的字母,则该字母在字符串中的出现次数必须至少相同。

    egg .有两个 g 's。如果字符串 $raw

    这是我的预期结果:

    Array([cat]=>'Yes',[rat]=>'No',[goat]=>'Yes',[total]=>'No',[egg]=>'No')
    

    我尝试了以下操作,但没有输出预期结果:

    $res=array();
    $raw="aabbcdfghmnejaachto";
    $word_array=array('cat','rat','goat','total','egg');
    $raw_array= str_split($raw);
    foreach($word_array as $word=>$value)
    {
        $word_value= str_split($value);
        foreach($word_value as $w=>$w_value)
        {
            foreach($raw_array as $raw=>$raw_value)
            {
                if(strcmp($w_value,$raw_value)==0)
                {
                    $res[$value]='Yes';
                }
                else
                {
                    $res[$value]='No';
                }
            }
        }
    }
    print_r($res);
    

    最初发布的代码丢失了这封信 e 从字符串 所以 鸡蛋 示例实际上会返回 No robinCTS

    7 回复  |  直到 9 年前
        1
  •  9
  •   robinCTS    9 年前
    • 您必须循环遍历 $words 数组,然后再次循环遍历每个单词的每个字符。
    • 每次迭代外部循环时,将默认结果值设置为 Yes .
    • 然后必须迭代当前单词的每个唯一字符。( array_count_values() )
    • 检查当前字符在单词中的出现次数是否大于当前字符在字母字符串中的出现次数。

    array\u count\u values() 用于内部循环,以避免在 $word $count 变量节省了两个 substr_count() 在if语句中调用。

    Demo )

    $string = "aabbcdfghmnejaachto";
    $words = array('cat','rat','goat','total','egg');
    foreach ($words as $word) {  // iterate each word
        $result[$word]='Yes';  // set default result value
        foreach (array_count_values(str_split($word)) as $char=>$count) {  // iterate each unique letter in word
            if ($count > substr_count($string, $char)) {  // compare current char's count vs same char's count in $string
                $result[$word]='No';  // if more of the character in word than available in $string, set No
                break;  // make early exit from inner loop, to avoid unnecessary iterations
            }
        }    
    }
    var_export($result);
    

    这是输出:

    array (
      'cat' => 'Yes',
      'rat' => 'No',
      'goat' => 'Yes',
      'total' => 'No',
      'egg' => 'No',
    )
    

    非常感谢 mickmackusa 对于 显著增强了这个答案。

        2
  •  2
  •   FKEinternet    9 年前

    您的问题是,您没有计算每个字符在 $raw $原始 。除非你做了某种形式的计数,或者复制 $原始 对于每个单词,在使用时删除字母,您将无法做到这一点。

        3
  •  2
  •   robinCTS    9 年前

    $res=array();
    $raw="aabbcdfghmnejaachto"; //tgrel -- to make all yes
    $res=array();
    $word_array=array('cat','rat','goat','total','egg');
    $raw_array= str_split($raw);
    $count_raw = array_count_values($raw_array);
    
    foreach($word_array as $value)
    {
        $word_value= str_split($value);
        $newArray = array_count_values($word_value);
        $res[$value]='yes';
        foreach($newArray as $char=>$number){
            if(!isset($count_raw[$char]) || $count_raw[$char]<$number){
                $res[$value]='No';
                break;
            }
        }
    }
    print_r($res);
    
        4
  •  1
  •   robinCTS    9 年前

    这里的错误很明显,您在单个字符测试中决定是否接受一个单词的值,虽然它应该基于单词的所有字母,但如果您只需要其值,则不需要同时精确数组的键和值 如中所示

    foreach($word_array as $value)
    

    in_array() ,使代码更加清晰

    $res=array();
    $raw="aabbcdfghmnejaachto";
    $res=array();
    $word_array=array('cat','rat','goat','total','egg');
    $raw_array= str_split($raw);
    
    foreach($word_array as $value)
    {
        $word_value= str_split($value);
        $res[$value]='yes';
        foreach($word_value as $w_value)
        {
            if (!in_array($w_value,$raw_array))
                $res[$value]='No';
    
        }
    }
    print_r($res);
    
        5
  •  1
  •   Axalix    9 年前

    让我们试着让它不带循环,但带闭包:

    $raw = "aabbcdfghmnejaachto";
    $word_array = ['cat', 'rat', 'goat', 'total', 'egg'];
    
    $result = [];
    $map = count_chars($raw, 1);
    array_walk(
        $word_array,
        function ($word) use ($map, &$result) {
            $result[$word] = !array_udiff_assoc(
                count_chars($word, 1), $map, function ($i, $j) { return $i > $j; }
            ) ? 'Yes' : 'No';
        }
    );
    
    1. count_chars($raw, 1) ,所以看起来像这样。

    $map:

    [
        97 => 4, // "97" is a code for "a"; and "4" - occurrence number.
        98 => 2,
        ...
    ]
    
    1. array_walk 通读单词并在期末考试中把每个单词加起来 $result Yes No 值来自与地图的比较,地图是为一个单词构建的。

    2. array_udiff_assoc 比较两个地图,丢弃原始地图中键相同且值较大的元素(与单词的地图相比)。而且 array\u udiff\u assoc()返回一个数组,其中包含array1中任何其他参数中不存在的所有值 array\u udiff\u assoc .

    Demo

        6
  •  0
  •   robinCTS    9 年前

    $res=array();
    $word_array=array('cat','rat','goat','total','egg');
    $raw="aabbcrdfghmnejaachtol";
    foreach($word_array as $word=>$value)
    {
        $raw_array= str_split($raw);
        $res[$value]='Yes';
        $word_value= str_split($value);
        foreach($word_value as $w=>$w_value)
        {
            if(!in_array($w_value,$raw_array))
            {
                 $res[$value]='No';
            }
            else
            {
                unset($raw_array[array_search($w_value, $raw_array)]);
            }
        }
    }
    

    如果像“total”一样使用一次,则不允许再次使用字符。

        7
  •  0
  •   Progrock    8 年前

    我们可以检查每个单词中的每个字母是否在给定的字母范围内,然后边走边拔出找到的字母。

    如果未找到字母,则以下功能短路。

    <?php
    function can_form_word_from_letters($word, $letters) {
        $letters      = str_split($letters);
        $word_letters = str_split($word);
        foreach($word_letters as $letter) {
            $key = array_search($letter, $letters);
            if($key === false) return;
            unset($letters[$key]); // Letter found, now remove it from letters.
        }
        return true;
    }
    
    $letters = "aabbcdfghmnejaachto";
    $words   = array('cat','rat','goat','total','egg');
    
    foreach($words as $word) {
        $result[$word] = can_form_word_from_letters($word, $letters) ? 'Yes' : 'No';
    }
    
    var_dump($result);
    

    array (size=5)
      'cat' => string 'Yes' (length=3)
      'rat' => string 'No' (length=2)
      'goat' => string 'Yes' (length=3)
      'total' => string 'No' (length=2)
      'egg' => string 'No' (length=2)