【问题标题】:Looking for the same chars in two strings in PHP在 PHP 中的两个字符串中寻找相同的字符
【发布时间】:2021-04-14 21:00:03
【问题描述】:

给定两个字符串,在 PHP 中检索共有字符和不共有字符的最佳方法是什么?

例如,给定两个字符串:

postcard

car

我想得到类似的东西:

letters in common: c - a - r
letters not in common: p - o - s - t - d

我看到有返回数值的单词相似度函数。

但是,我想检索每个字符

我的方法是将两个字符串都视为数组(使用str_split),然后检查最短字符串中的元素是否存在于较长字符串中(使用in_array)。

$arr_postcard = str_split($postcard);
$arr_car = str_split($car);
$notcommon = array();
   if (in_array($arr_postcard, $arr_car) == false){
       array_push($notcommon, $arr_car);
   }
   foreach($notcommon as $k => $v){
      print_r ($v);
   }

上面的代码似乎不起作用。它返回$arr_car 的值。

也许还有其他方法。

【问题讨论】:

  • 我的方法是一个好的开始,可能有很多不同的方法,但你可以从你认为可以解决这个问题的方法开始。
  • 我试图编辑我的问题添加一些代码。

标签: php arrays string character similarity


【解决方案1】:

一个简单的方法:

<?php

$postcard = 'paccoi';
$car = 'coi';

$arr_postcard = str_split($postcard);
$arr_car = str_split($car);


function array_diff_once($array1, $array2) {
    foreach($array2 as $a) {
        $pos = array_search($a, $array1);
        if($pos !== false) {
            unset($array1[$pos]);
        }
    }

    return $array1;
}

$uncommon = count($arr_postcard) >= count($arr_car) ?  array_diff_once($arr_postcard,$arr_car) : array_diff_once($arr_car,$arr_postcard);

echo 'Letters not in common: ' . implode(' - ', $uncommon) . PHP_EOL;

function array_intersect_once($array1, $array2) {
    $array = [];
    foreach($array1 as $a) {
        $pos = array_search($a, $array2);
        if($pos !== false) {
            $array[] = $a;
        }
    }

    return $array;
}
$common = count($arr_postcard) >= count($arr_car) ?  array_intersect_once($arr_car,$arr_postcard) : array_intersect_once($arr_postcard,$arr_car);

echo 'Letters in common: ' . implode(' - ', $common) . PHP_EOL;

输出: https://3v4l.org/lY755https://3v4l.org/kK9sE

注意:- 您可以在str_split() 中使用trim() 来解决字符串带有前导或尾随空格的问题。

参考: Keep Duplicates while Using array_diff

【讨论】:

    【解决方案2】:

    我会选择以下内容。 拆分字符串以获得每个单独的字符,并使用值翻转键,使所有单独的字符都是键。 (使用array_flip

    现在我们可以使用带有一些基本集合操作的键,例如array_intersect_key 来获取交集以获取两个字符串中的字符。 我们可以应用array_diff_key 来获取集合的差异(因此第一个字符串中的那些字符而不是另一个字符串中的那些字符)。

    $s1 = array_flip(str_split('postcard'));
    $s2 = array_flip(str_split('car'));
    
    $intersection = array_intersect_key($s1, $s2);
    $difference = array_diff_key($s1, $s2);
    
    echo 'Letters in common: ' . implode(' - ', array_keys($intersection)) . PHP_EOL;
    echo 'Letters NOT in common: ' . implode(' - ', array_keys($difference)) . PHP_EOL;
    

    上面确实是为了吐出独特的字符(注释集)。下面的一段代码我假设是你想要实现的:

    function outputResult(string $s, bool $inCommon = true)
    {
        $result = 'Letters';
    
        if (!$inCommon) {
            $result .= ' NOT';
        }
    
        $result .= ' in common: ';
        $result .= !empty($s) ? implode(' - ', str_split($s)) : 'NONE';
    
        echo $result . PHP_EOL;
    }
    
    // Count for both the occurrences of each char.
    $s1 = array_count_values(str_split('paccoi'));
    $s2 = array_count_values(str_split('coi'));
    
    $mostUniqueChars = $s1;
    $leastUniqueChars = $s2;
    
    // For now I assumed the string with most unique characters
    // is the one you want to test. Could ofcourse output them both
    // ways if you wrap all logic in a function. (note that intersection
    // is the same both ways)
    if (count($s2) > count($s1)) {
        $mostUniqueChars = $s2;
        $leastUniqueChars = $s1;
    }
    
    $intersect = '';
    $diff = '';
    foreach ($mostUniqueChars as $char => $count) {
        // Get the number of characters in common (and how frequent)
        $common = min($count, ($leastUniqueChars[$char] ?? 0));
        // As an alternative you could add common and difference to an array to keep
        // the counts, but I chose to repeat it and concat it to a string.
        if ($common > 0) {
            $intersect .= str_repeat($char, $common);
        }
    
        // Calculate the difference between first string and second string
        // in case difference has a value <= 0 then string 2 had more occurrences
        // of the character.
        $difference = $count - ($leastUniqueChars[$char] ?? 0);
        if ($difference > 0) {
            $diff .= str_repeat($char, $difference);
        }
    };
    
    // Note that both strings $intersect and $diff contain
    // all the characters, you could also output these directly.
    outputResult($intersect);
    outputResult($diff, $inCommon = false);
    

    输出:

    Letters in common: c - o - i
    Letters NOT in common: p - a - c
    

    【讨论】:

    • 这是一个有趣的解决方法@Remy。我不知道array_intersect_key
    • 我猜字母重复有问题。一旦一个字母存储在数组$difference 中,该字母的所有出现都将被搁置一旁。
    • 尝试使用字符串:paccoicoi。你会看到问题。
    • 通过您编辑的函数,您解决了问题。我需要时间来看看你做了什么。
    猜你喜欢
    • 1970-01-01
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 2021-06-01
    • 2017-03-24
    • 2016-08-30
    • 2014-10-18
    相关资源
    最近更新 更多