skip to Main Content

I have an array that I read from a file, and I’m trying to remove all the possibilities from that array but keep the originating number.

$n = Array
(
    [0] => 050
    [1] => 051
    [2] => 052
    [3] => 501
    [4] => 054
    [5] => 150
    [6] => 061
    [7] => 062
    [8] => 510
    [9] => 064
)

In my code, I loop the file into an array, and then I have a function called combo, which gives me all possible combinations of that number ex: 051 can be 150, 510, 501.

My combo function is as follows:

function combo($num){
    
    $a = array();
    $n_s = str_split($num);
    
    
    // 5 8 2
    
    // first combo
    $c1 = $n_s[0] . '' . $n_s[2] . '' . $n_s[1];
    $c2 = $n_s[1] . '' . $n_s[0] . '' . $n_s[2];
    $c3 = $n_s[1] . '' . $n_s[2] . '' . $n_s[0];
    $c4 = $n_s[2] . '' . $n_s[0] . '' . $n_s[1];
    $c5 = $n_s[2] . '' . $n_s[1] . '' . $n_s[0];
    

    array_push($a, $c1, $c2, $c3, $c4, $c5);
    
    return($a);
    
}


function mirror($n){
    
    $m = array("0" => "5", "1" => "6", "2" => "7", "3" => "8", "4" => "9", "5" => "0", "6" => "1", "7" => "2", "8" => "3", "9" => "4");
    
    
    $n_s = str_split($n);
    
    $f = $m[$n_s[0]] . '' . $m[$n_s[1]] . '' . $m[$n_s[2]];

    return $f;

}
foreach($n as $v){
        echo $v . '<br>';

        $t = combo($v);
        
        foreach($t as $vs){
            unset($n[$vs]);
        }
}

So what I am looking for as a result would return the original array, keeping the 051, and removing the 501, 150, 510 variations. This will work under a loop for 250 numbers. If my math is right, it should return a final array approximately with 25 numbers.

Any help is appreciated, I can’t seem to get this right, and I’m missing something.

2

Answers


  1. I’ve taken the idea of converting 051,501,150,510 all into 015 so that duplicates can be filtered out, then using array_intersect_key to take the keys of what is left and use that to return values from the original array.

    // Converted to string since you want to keep your leading zero?
    $array = [ '050','051','052','501','054','150','061','062','510','064' ];
    
    // sort each digit in each array item so we can apply array_unique to the entire set of numbers to remove duplicates
    $reduced = array_unique( array_map( function( $n ){
        $number = str_split( $n );
        sort($number);
        return implode( '', $number );
    }, $array ) );
    
    // Use the keys from this new array to extract the values from the original array
    $output = array_intersect_key( $array, $reduced );
    
    // done!
    print_r( $output );
    

    Returns

    Array
    (
        [0] => 050
        [1] => 051
        [2] => 052
        [4] => 054
        [6] => 061
        [7] => 062
        [9] => 064
    )
    
    Login or Signup to reply.
  2. I don’t see any way to more simply the sort the digits than splitting, sorting, then imploding.

    Beyond that, I suppose using null coalescing assignment operators will allow you to retain the first occurring set of digits within a single loop over the data.

    Code: (Demo)

    $result = [];
    foreach ($array as $i => $number) {
        $sortable = str_split($number);
        sort($sortable);
        $key = implode($sortable);
        $lookup[$key] ??= $i;  // keep $i from first $key
        $result[$lookup[$key]] ??= $number;  // keep first $number from first $key
    }
    var_export($result);
    

    If you want a re-indexed result: Demo

    $result = [];
    foreach ($array as $i => $number) {
        $sortable = str_split($number);
        sort($sortable);
        $key = implode($sortable);
        if (!isset($lookup[$key])) {
            $lookup[$key] = true;
            $result[] = $number;
        }
    }
    var_export($result);
    

    *Both of the above scripts enjoy a more efficient/lower time complexity versus Scuzzy’s answer because my scripts only use a single loop to do it all.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search