【问题标题】:Array compare and count which has similar values and which not数组比较和计数具有相似值和不相似的值
【发布时间】:2016-04-07 23:04:42
【问题描述】:

我有一种情况,我必须比较动态数组,并且只为前四个键获取具有相似值的数组计数。例如:

Array[0]
(
    [item] => 1
    [size] => 1
    [pair] => 1
    [pay] => 1
    [name] => 
    [msg] => 
    [email] => 
    [b19e19b13682bcfef93651c86f9ad9e6] => eih6j74035oj17bvnses32km23
)
Array[1]
(
    [item] => 1
    [size] => 2
    [pair] => 1
    [pay] => 1
    [name] => 
    [msg] => 
    [email] => 
    [b19e19b13682bcfef93651c86f9ad9e6] => eih6j74035oj17bvnses32km23
)
Array[2]
(
    [item] => 1
    [size] => 2
    [pair] => 2
    [pay] => 2
    [name] => 
    [msg] => 
    [email] => 
    [b19e19b13682bcfef93651c86f9ad9e6] => eih6j74035oj17bvnses32km23
)
Array[3]
(
    [item] => 1
    [size] => 1
    [pair] => 1
    [pay] => 1
    [name] => 
    [msg] => 
    [email] => 
    [b19e19b13682bcfef93651c86f9ad9e6] => eih6j74035oj17bvnses32km23
)

我有上面一组数组,其中第一次和最后一次迭代具有相似的值(对于第一个四个键)。为此,我必须推导出(0,3),(1),(2)之类的东西。有什么解决办法吗?

【问题讨论】:

  • 你尝试过什么吗?你先谷歌了吗?
  • 您有 4 条修复记录,或者它可能非常符合您的代码?
  • 是的。我尝试了 if 条件,但它有大约 30 种组合。但如果再添加一个键,它可能会增加。谷歌也搜索了,但没有找到解决方案。
  • 你能定义相似的值吗?就像一模一样或者你是什么意思?

标签: php arrays


【解决方案1】:

这应该可以正常工作:

像我在$arrays 中所做的那样,将你的数组放在一个数组中,然后:

<?php
$arrays = [
array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4),
array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4),
array('a'=>1, 'b'=>2, 'c'=>3, 'd'=>4),
array('a'=>1, 'b'=>2, 'c'=>4, 'd'=>3),
];

$result = [];

//get the keys of a sub-array that is inside $arrays, to be used later
$keys = array_keys($arrays[0]);

for($i=0; $i < sizeof($arrays); $i++){

    $sa = array(); // to store similar arrays indexes

    for($k=$i+1; $k < sizeof($arrays); $k++){

        $similar = false;

        //compare the values of keys in the two arrays. Just compare the first 4 keys (as the user's desire)
        for($j=0; $j < 4; $j++){

            //check if the values are similar, if they are, assign $similar to true, and assign $j=3 to end the loop, (a bit of laziness here)
            ($similar = $arrays[$i][$keys[$j]] == $arrays[$k][$keys[$j]] ? true : false) ? null : ($j=3); 
        }

        // check if the key (which represents an index in $arrays) is in $sa or not, if not, push it.
        $similar ? (in_array($i, $sa) ? null : array_push($sa, $i) && in_array($k, $sa) ? null : array_push($sa, $k)) : null;
        //if $similar is true, make $i jumps to the $k index (saving time)
        $similar ? $i=$k : null;
    }

    //if $sa not empty, push it to $result
    empty($sa) ? null : ($result[] = $sa);
}

/* 
// at this stage, $result includes all the similar arrays
// so we need another loop to push the unique arrays to $result
// just check if an index of $arrays is in an sub-array of $result, if not, push it as an array of one record 
*/

for($j=0; $j < sizeof($arrays); $j++){
    $f = false;
    for($i=0; $i < sizeof($result); $i++){
        in_array($j, $result[$i]) ? $f = true : null;
    }
    if(!$f){
        $sa = array();
        array_push($sa, $j);
        array_push($result, $sa);
    }
}

最后,$result 是一个数组数组,每个子数组值代表一个 $arrays 的索引 如果结果输出是:

array(2) { 
    [0]=> array(3) { 
            [0]=> int(0) 
            [1]=> int(1) 
            [2]=> int(2) 
    },
    [1]=> array(1) { 
            [0]=> int(3) 
    } 
}

这意味着 $arrays 有两组子数组, 其中 $arrays[0]、$arrays[1] 和 $arrays[2] 相似(第 1 组),则 $arrays[3] 是唯一的(第 2 组)

注意:如果有人可以优化我的答案,我将不胜感激。

【讨论】:

  • 虽然这段代码 sn-p 可以解决问题,但代码外的including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!
  • @Mohammad,result 输出为array(2) { [0]=&gt; array(3) { [0]=&gt; int(0) [1]=&gt; int(1) [2]=&gt; int(2) } [1]=&gt; array(1) { [0]=&gt; int(3) } }。你能解释一下吗?
  • @RomanPerekhrest $result中的每个数组代表一组相似的数组,其中的值是$arrays的索引
【解决方案2】:

就个人而言,我更喜欢 OOP 方法:更干净、可重用...

用法

$o = new SOF_ArrayComapare($yourInputArray, array('item', 'size', 'pair', 'pay', 'name'));
$arraysEqual = $o->getEqualArrays();
print $o->toString();

类定义

class SOF_ArrayComapare {
    private $_keysToMatch   = array();
    private $_array         = array();

    public function __construct($array, $keysToMatch) {
        $this->_array       = $array;
        $this->_keysToMatch = $keysToMatch;
    }

    private $_equalArrays   = array();
    private $_indexToEscape = array();

    public function getEqualArrays() {
        $size = count($this->_array);
        for ($i=0 ; $i<$size ; $i++) {

            if (in_array($i, $this->_indexToEscape))    continue;
            else                                        $this->_indexToEscape[] = $i;

            $this->_equalArrays[$i][] = $i;
            for ($j=($i+1) ; $j<$size ; $j++) {
                if (in_array($j, $this->_indexToEscape)) continue;
                if ($this->areEquals($this->_array[$i], $this->_array[$j])) {
                    $this->_indexToEscape[]     = $j;
                    $this->_equalArrays[$i][]   = $j;
                }
            }   
        }
        return $this->_equalArrays;
    }

    private function areEquals($a1, $a2) {
        foreach($this->_keysToMatch as $key) {
            if(
                !isset($a1[$key]) || 
                !isset($a2[$key]) ||
                $a1[$key] !== $a2[$key]
            ) {
                return FALSE;
            }
        }
        return TRUE;
    }

    public function toString($htmlFormat = TRUE) {
        $newLine = ($htmlFormat === TRUE) ? '<br />' : "\n";
        $report = "These arrays are equals: " . $newLine;
        foreach($this->_equalArrays as $array) {
            $report .= '(' . implode(',', $array) . ')' . $newLine;
        }
        return $report;
    }
}

【讨论】:

    【解决方案3】:

    我将在最后解释这一点,但代码非常自我解释:

    function getDuplicatesArray()
    {
        $foundIndexes = array();
        $arraysCount = count(Array);
        $resultArray = array();
        // $i is current index
        // $j is compared index
        for ($i = 0; i < $arraysCount; i++)
        {
            if (in_array($i, $foundIndexes))
                continue;
    
            $currentResultArray = array($i);
    
            for ($j = $i+1; $j<$arraysCount; $j++)
            {
                if (in_array($j, $foundIndexes))
                    continue;
                if(areFirstValsSame($i,$j))
                {   
                    $currentResultArray[] = $j;
                    if (count($currentResultArray) == 2) // first j for this i
                        foundIndexes[] = $i;
                    foundIndexes[] = $j;
                }       
            }
            $resultArray[] = $currentResultArray;
        }//.. for i
    }//.. getDuplicatesArray
    
    function areFirstValsSame($index1, $index2){
        $toCompare = 4;
        for ($i=0; i<$toCompare; i++)
            if (Array($index1, i) != Array($index2, i)
                return false;
        return true; 
    }
    

    一个“找到”的数组保存所有具有重复项的索引。

    当找到一个重复的数组的索引被添加到“找到”。

    current-found 保存与当前数组进行比较的重复数组的所有索引。

    然后在测试下一个索引之前,检查之前是否找到它,如果是则跳过它。

    一旦比较了一个索引(无论是否找到重复),它的当前找到的就会被添加到结果中。

    如果所有四个数组都相同,你会得到:(0,1,2,3),如果第一个和第三个是重复的,第二个和第四个你会得到:(0,2),(1,3) 等等。

    您不会重复检查两次。但是您仍然需要重新读取那些未发现与迄今为止检查的索引重复的数组的值。

    这可以通过递归进行优化,但会占用更多内存,而且对于这么少量的数组,它甚至不会被注意到。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-11
      • 1970-01-01
      • 1970-01-01
      • 2017-08-03
      相关资源
      最近更新 更多