数组比较和计数,找出相似值和不同值。

4

我有一个情况需要比较动态数组,并且只针对前四个key的相似值计数。例如:

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)的东西。是否有解决方案?


1
你有尝试过什么吗?你先在谷歌上搜索了吗? - Lino
你有4个固定记录,或者根据你的代码可能会有所不同? - jilesh
是的。我尝试了if条件,但它会产生大约30种组合。但如果再添加一个键,可能会增加。我也在谷歌上搜索了,但没有找到解决方案。 - Manikandan K
可能与此重复 https://dev59.com/TpDea4cB1Zd3GeqPhNno#33781903 - max
1
你能定义一下“相似值”吗?是指完全相同还是有其他含义? - Rizier123
将用于比较的键的值使用适当的分隔符(这些值似乎是数字,您可以使用破折号、逗号、字母或其他非数字字符)组合成单个值。将您需要的项目复制到一个新数组中,使用新生成的值作为键来识别从“相似值”创建的新条目。 - axiac
3个回答

0

这应该可以正常工作:

像我在$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]相似(第一组),而$arrays[3]是独特的(第二组)

N.B: 如果有人能优化我的答案,我将不胜感激。


1
虽然这段代码片段可能解决了问题,但是在代码之外加入解释真的有助于提高您的帖子质量。请记住,您正在为未来的读者回答问题,而这些人可能不知道您的代码建议原因。同时,请尽量不要在代码中添加过多的解释性注释,这会降低代码和解释的可读性! - Rizier123
@Mohammad,result输出是array(2) { [0]=> array(3) { [0]=> int(0) [1]=> int(1) [2]=> int(2) } [1]=> array(1) { [0]=> int(3) } }。你能解释一下吗? - RomanPerekhrest
@RomanPerekhrest $result 中的每个数组都代表一组相似的数组,其中值是 $arrays 的索引。 - Mohammad

0

个人而言,我更喜欢面向对象的编程方法:更加清晰、可重用...

使用方法

$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;
    }
}

0

我会在最后解释这个,但是代码本身非常容易理解:

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; 
}

一个“found”数组保存所有带有重复的索引。

当发现重复时,将数组的索引添加到“found”中。

当前找到的保存了与当前数组进行比较的重复数组的所有索引。

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

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

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

你不会检查重复两次。但你仍然需要重新读取那些没有找到重复的数组的值,直到现在为止检查的索引。

这可以通过递归来优化,但会占用更多的内存,在这么少量的数组中,甚至不会被注意到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接