A PHP interview question, let's take a look

WBOY
Release: 2023-03-03 08:58:02
Original
1038 people have browsed it

<code class="php">$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],
    ...
];</code>
Copy after login
Copy after login

Define a function and pass in $listData
If the elements in 111 are duplicated with the elements in 222/333/444..., return false
If the elements in 222 are the same as 111/333/444 ... If the elements inside are repeated, return false
If the elements inside 333, and the elements inside 111/222/444... are repeated, return false
If...

Allow the elements in 111/222/333/444 to be repeated and return true
Return true in other cases


Known:
$listData length is unknown
111/222/333/444... The length of
111/222/333/444... is unknown. The elements in

111/222/333/444... are strings and numbers


I implemented it myself, and I feel that the algorithm is terrible. Is there any other method?
<code class="php">function test ($array) {

    $tempValueList  = [];
    foreach ($array as $key => $valueList) {
        
        foreach ($valueList as $value) {
            
            $tempValueList[]    = $key . '~' . $value;
        }
    }
    $result         = true;
    foreach ($array as $key => $valueList) {
        
        foreach ($valueList as $value) {
            
            foreach ($tempValueList as $_value) {
                
                $pos    = strpos($_value, '~');
                $_key   = substr($_value, 0, $pos);
                $_val   = substr($_value, $pos + 1);

                if ($key == $_key) {

                    continue;
                }
                if ($_val == $value) {

                    $result = false;
                    break 3;
                }
            }
        }
    }

    return      $result;
}</code>
Copy after login
Copy after login

Reply content:
<code class="php">$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],
    ...
];</code>
Copy after login
Copy after login


Define a function and pass in $listDataIf the elements in 111
are duplicated with the elements in 222/333/444..., return false If the elements in 222
are the same as 111/333/444 ... If the elements inside are repeated, return false If the elements inside 333
, and the elements inside 111/222/444... are repeated, return false

If...


Allow the elements in 111/222/333/444 to be repeated and return true

Return true in other cases


Known:
$listData length is unknown
111/222/333/444... The length of

111/222/333/444... is unknown. The elements in
111/222/333/444... are strings and numbers

I implemented it myself, and I feel that the algorithm is terrible. Is there any other method?

<code class="php">function test ($array) {

    $tempValueList  = [];
    foreach ($array as $key => $valueList) {
        
        foreach ($valueList as $value) {
            
            $tempValueList[]    = $key . '~' . $value;
        }
    }
    $result         = true;
    foreach ($array as $key => $valueList) {
        
        foreach ($valueList as $value) {
            
            foreach ($tempValueList as $_value) {
                
                $pos    = strpos($_value, '~');
                $_key   = substr($_value, 0, $pos);
                $_val   = substr($_value, $pos + 1);

                if ($key == $_key) {

                    continue;
                }
                if ($_val == $value) {

                    $result = false;
                    break 3;
                }
            }
        }
    }

    return      $result;
}</code>
Copy after login
Copy after login

After taking a look, the two previous answers are unusable. LZ is really miserable. .

My definition of subarray is a single array like ['a', 'b', 'c', 'a'].

My answer:

<code>$result = array();
foreach ($listData as $line) {
    //子数组内部去重,再组装回原来的格式
    $result[] = array_unique($line);
}

//子数组先去重再合并的结果数量 和 先合并子数组再去重的结果数量 做比较。
//如果是相同的,意味着不存在跨子数组的重复,只存在子数组内部重复,所以`True`
var_dump(count(array_merge(...$result)) === count(array_unique(array_merge(...$listData))));</code>
Copy after login

My answer calls system functions more times and looks simpler. However, a large part of functions such as PHP array_xxx have no performance advantages. If these functions are not used, the operating efficiency can be relatively improved.

Currently, @springhack is the most efficient. And it can maintain maximum efficiency in every situation.

Easy to understand auxiliary reference information:

Original data:

<code>$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j']
];
</code>
Copy after login

Then $result ends up looking like this:

<code>$listData = [
        '111' => ['a', 'b', 'c'],
        '222' => ['d', 'e', 'f', 'b'],
        '333' => ['g', 'h'],
        '444' => ['i', 'j']
];
</code>
Copy after login

The result of sub-array deduplication first and then merging

<code>Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => d
    [4] => e
    [5] => f
    [6] => b
    [7] => g
    [8] => h
    [9] => i
    [10] => j
)
</code>
Copy after login

Used to compare the quantity (number of array elements) with the above, the so-called "result of merging sub-arrays first and then removing duplicates":

<code>Array
(
    [0] => a
    [1] => b
    [2] => c
    [4] => d
    [5] => e
    [6] => f
    [9] => g
    [10] => h
    [11] => i
    [12] => j
)</code>
Copy after login

Loop once and find the intersection of the current element and all other elements. The code is as follows:

<code>    function isExistsInOther($data)
    {
        $temp = [];
        $isExists = true;
        foreach ($data as $key=>$value) {
            $temp = $data;
            unset($temp[$key]);
            if(!$isExists) break;
            @array_walk($temp,function($v,$k) use($value,&$isExists){
                if($isExists) {
                    $intersect = array_intersect($v,$value);
                    if(!empty($intersect)) {
                        $isExists = false;
                    }
                }
            });
        }
        return $isExists;
    }
    
    $listData = [
        '111' => ['a', 'k', 'c', 'a'],
        '222' => ['d', 'e', 'f', 'f', 'b'],
        '333' => ['g', 'e'],
        '444' => ['i', 'j']
    ];
    $result = isExistsInOther($listData);
    var_dump($result);
    //true  无交集
    //false 有交集</code>
Copy after login

<code>/**
 * [checkRepeat 检查每个key的数组值是否与其它的有重复值]
 * @param  [type] $listData [检查的数组]
 * @return [type]           [array]
 */
function checkRepeat($listData) {
    foreach($listData as $key =>$val) {
        $check_arr = $listData;
        // 删除当前key
        unset($check_arr[$key]);
        // 合并删除后的数组
        $check_arr = array_merge(...$check_arr);
        // 判断是否存在交集
        $rs[$key] = count(array_intersect($val, $check_arr)) > 0 ? false : true ;
    }
    return $rs;
}

$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],

];
$rs = checkRepeat($listData);</code>
Copy after login
<code>function check($arr)
{
  $chk = [];
  foreach ($arr as $k => $v)
    foreach ($v as $i)
    {
      if (isset($chk[$i] && $chk[$i] != $k)
        return false;
      $chk[$i] = $k;
    }
  return true;
}</code>
Copy after login

The claw machine code should be the most efficient, so you can debug it yourself.

Since the answers are given above, let me add to you, multi-dimensional array deduplication

<code>/**
 * 多维数组去重
 * @param array 
 * @return array
 */
function super_unique($array)
{
    $result = array_map("unserialize", array_unique(array_map("serialize", $array)));

    foreach ($result as $key => $value)
    {
        if ( is_array($value) ) {
            $result[$key] = super_unique($value);
        }
    }

    return $result;
}</code>
Copy after login

Multi-dimensional array deduplication

<code>$listData = array_values($listData);
foreach ($listData as $k => $v) {
    foreach ($listData as $n => $m) {
        if($k == $n) continue;
        if(array_intersect($v , $m)){
            echo $k.$n.'false <br>';
        }
        else{
            echo $k.$n.'true <br>';
        }
    }
}</code>
Copy after login

My answer (principle: loop to find intersection):

<code><?php
$list = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f','b'],
    '333' => ['g', 'h','c'],
    '444' => ['i', 'j']
];
function jiaoji($array){
    $listData = array_values($array);
    $list = [];
    for ($i = 0; $i < count($listData); $i++) {
        for ($j = $i+1; $j < count($listData); $j++) {
            $list[] = array_intersect($listData[$i],$listData[$j]);
        }
    }
    $result = array_filter($list);
    return count($result)==0;
}
var_dump(jiaoji($list));//bool(false)
?></code>
Copy after login

Can you understand it this way? As long as the values ​​in this array intersect with each other, false will be returned. . .

array_intersect() function seems to work. But the problem is to convert the values ​​in an array into a small array to pass values.

<code><?php
$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],
    ...
];

function getArr($listData){
    $isUnsetFirstKey = false;
    $len = count($listData);
    if($len<=1) return false;
    $firstKey = key($listData);
    $firstArr = array_unique($listData[$firstKey]);
    $newList = $listData;
    unset($newList[$firstKey]);
    foreach ($newList as $key => $val) {
        $arr = array_unique($val);
        $newarr = array_merge($firstArr,$arr);
        if(count($newarr) != count(array_unique($newarr))){
            $isUnsetFirstKey = true;
            unset($newList[$key]);
            echo $key . "<br>";
        }
    }
    if($isUnsetFirstKey) echo $firstKey . "<br>";
    getArr($newList);
}

getArr($listData);
?></code>
Copy after login

Check out my answer, it’s amazing


One-dimensional arrays are similar to two-dimensional arrays. The judgment is made internally. The following is the method for two-dimensional arrays. One-dimensional arrays are skipped. 🎜Compare the array length before and after the array merging (then take unique)🎜
<code class="php">function check_repeat($arr){
    $after_arr = [];
    // 对比自身
    foreach($arr as $index => $value){
        $arr[$index] = $after_arr = array_unique($value);
        if(count($value) !== count($after_arr)){
            return true;
        }
    }
    // 对比其他
    $temp = array_shift($arr);
    $cnt  = count($temp);
    foreach ($arr as $index => $value) {
        $cnt += count($value);
        $temp = array_merge($temp, $value);
    }

    return $cnt !== count(array_unique($temp)) ? true : false;
}

$listData = [
    '111' => ['a', 'b', 'c',],
    '222' => ['d', 'e', 'f',],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],
];

var_dump(check_repeat($listData));
</code>
Copy after login

<code>function test($listData) {
    $result = array_map('array_unique', $listData);
    foreach ($result as $key => $value) {
        $keys = array_values(array_diff(array_keys($result),[$key]));
        for($i = 0; $i <= count($keys); $i ++) {
            $data = array_merge_recursive($data,$result[$keys[$i]]);
            if ($i == (count($keys) -1) ) {
                $res = array_intersect($value, $data);
            }
        }
        $data = [];
    }
    return !empty($res) === true ? false : true;
}</code>
Copy after login

<code><?php

$listData = [
    '111' => ['a', 'b', 'c', 'a'],
    '222' => ['d', 'e', 'f', 'f', 'b'],
    '333' => ['g', 'h'],
    '444' => ['i', 'j'],
];

$temp = array();
foreach ($listData as $key => $xxx) {
    foreach ($xxx as $value) {
        if (in_array($value, $temp)) {
            echo $value.' from '.$key.' is in array';
            exit();
        }
    }
    $temp = array_merge($temp, $xxx);
}
echo 'You should get a True!';
</code>
Copy after login

没几行,满足需求。

A PHP interview question, let's take a look

还原之前那个
shiji 的答案

先array_pop,取出最后一项。再取items数组的并集。if并集与最后一项有交集则返回true(表重复)。循环执行。

根据 @大呜 的算法改良了一下。

<code>function checkRepeat2($listData)
{
    $check_arr = $listData;
    foreach ($listData as $key => $val) {
        //之前比较过的key无需再比较
        unset($check_arr[$key]);
        if ($check_arr) {
            // 合并删除后的数组,判断是否存在交集
            //As PHP 5.6 you can use array_merge + "splat" operator to reduce a bidimensonal array to a simple array:
            if (array_intersect($val, array_merge(...$check_arr))) {
                return false;
            }
        }
    }
    return true;
}</code>
Copy after login

不知道是不是这样:

<code>$new_arr = [];
foreach ($listData as $key => $value) {
    foreach ($value as $k => $v) {
        $kv = $k . $v;
        if (in_array($kv, $new_arr)) {
            echo '有重复';exit;
        } else {
            $new_arr[] = $kv;
        }
    }
}</code>
Copy after login
Related labels:
php
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template