6

I want to remove duplicates where either measurement or altunit matches another array, but ignoring if they're blank.

Array
(
    [0] => Array
        (
            [id] => 2
            [altunit] => %
            [measurement] => 
        )

    [1] => Array
        (
            [id] => 3
            [altunit] => 
            [measurement] => 6
        )

    [2] => Array
        (
            [id] => 4
            [altunit] => %
            [measurement] => 
        )

    [3] => Array
        (
            [id] => 5
            [altunit] => 
            [measurement] => 6
        )

    [4] => Array
        (
            [id] => 6
            [altunit] => 
            [measurement] => 6
        )

)

Becomes

Array
(
    [0] => Array
        (
            [id] => 2
            [altunit] => %
            [measurement] => 
        )

    [1] => Array
        (
            [id] => 3
            [altunit] => 
            [measurement] => 6
        )

)

Best I can come up with is:

$test = array ( 0 => array ( 'id' => '2', 'altunit' => '%', 'measurement' => NULL, ), 1 => array ( 'id' => '3', 'altunit' => NULL, 'measurement' => '6', ), 2 => array ( 'id' => '4', 'altunit' => NULL, 'measurement' => '6', ), 3 => array ( 'id' => '5', 'altunit' => NULL, 'measurement' => '6', ), 4 => array ( 'id' => '6', 'altunit' => NULL, 'measurement' => '6', ), );

$num = [];
foreach($test as $k => $v) $num[] = $v['measurement'];

But this only works for measurement, and removes the id and altunit keys.

6 Answers 6

3

Humm, Make an array of 'knowed value' for measurement and altunit and then check it it exist on the rest of the values.

something like:

$knowed_altunit=array();
$knowed_measurement=array();

foreach($test as $k=>$v){
  if(in_array($v['altunit'],$knowed_altunit) 
  || in_array($v['mesurement'],$knowed_measurement)){
    //if the value of altunit or measurement is already knowed then remove the entry from the array,
    unset($test[$k]);
  }else{
   //if it never been seen, add it so further entry can be checked agaisnt the knowed value
   $knowed_altunit[]=$v['altunit'];
   $knowed_measurement[]=$v['mesurement'];
  }
}

Sorry if any typo but thins might help you wrap your head around the solution to your problem.

Sign up to request clarification or add additional context in comments.

Comments

2

You can try this code:

<?php

    /* before you need to check that $test variable is declarated and have all items to check */
    $values_altunit = array();
    $values_measurement = array();
    $result = array();

    foreach($test as $key => $value) {
        /* check if exist altunit and measurement values in blacklist arrays */
        if (!in_array($value['altunit'], $values_altunit) && !in_array($value['measurement'], $values_measurement)) {
            /* if not exist, add the item to $result array */
            $result[$key] = $value;
            /* and add altunit and measurement values to blacklist arrays */
            $values_altunit[] = $value['altunit'];
            $values_measurement[] = $value['measurement'];
        }
    }

    /* print result items */
    var_dump($result);

?>

3 Comments

Pretty much the same logic as my answer but i think blacklist is a better name :P Apart from the fact that this answer requires a new array instead of unsetting value from the original array.
Yes, our answers are similar but i'm creating a new array instead of unset values.. The difference in our answer time are seconds :)
I like to keep my memory_get_usage() low, this is why i rather unset value from an existing array than create a new one and duplicate values. Personal preference, just saying :) I still upvoted your answer :P
1

This is a short code that can give the result for unique measurements

  <?php 

    $arr = array(
        "0"=> array        (
                "id" => 2,
                "altunit" => "%",
                "measurement" => "",
            ),

        "1"=> array        (
                "id" => 3,
                "altunit" => "",
                "measurement" => 6,
            ),

        "2"=> array        (
                "id" => 4,
                "altunit" => "%",
                "measurement" => "",
            ),

        "3"=> array        (
                "id" => 5,
                "altunit" => "",
                "measurement" => 6,
            ),

        "4"=> array        (
                "id" => 6,
                "altunit" => "",
                "measurement" => 6,
            )

    );

    $unique_measure = $new_array  = array();
    foreach($arr as $sup_key => $sup_val){
        foreach($sup_val as $sub_key => $sub_val){
            if(!in_array($sup_val['measurement'], $unique_measure)){
                array_push($unique_measure, $sup_val['measurement']);
                array_push($new_array,$sup_val);

            }

        }
    }

    print_r($new_array);
?>

Output :

  Array
    (
        [0] => Array
            (
                [id] => 2
                [altunit] => %
                [measurement] => 
            )

        [1] => Array
            (
                [id] => 3
                [altunit] => 
                [measurement] => 6
            )

    )   

try this code. it may do the trick.

One More approach to your problems solution can be removing that particular key from the main array using unset(your_array_key) will do the trick in the same code.

Comments

1

Try, this may help you

function remove_dup($array, $keys )
{
    $out = array();

    foreach($array as $sub)
    {
        if(empty($out))
        {   
            $out[] = $sub;
            continue;
        }

        foreach($keys as $key)
        {   
            if($flag=in_array( $sub[$key],array_map(function($e) use($key){ return $e[$key];}, $out)) )
                break;
        }

        if(!$flag)
            $out[] = $sub;
    }

    return $out;
}

// Usage
print_r( remove_dup($array, array('altunit','measurement') ) );

Test

[akshay@localhost tmp]$ cat test.php 
<?php

function remove_dup($array, $keys )
{
    $out = array();

    foreach($array as $sub)
    {
        if(empty($out))
        {   
            $out[] = $sub;
            continue;
        }

        foreach($keys as $key)
        {   
            if($flag=in_array( $sub[$key],array_map(function($e) use($key){ return $e[$key];}, $out)) )
                break;
        }

        if(!$flag)
            $out[] = $sub;
    }

    return $out;
}

$array = array(
        "0"=> array      (
                "id" => 2,
                "altunit" => "%",
                "measurement" => "",
            ),

        "1"=> array        (
                "id" => 3,
                "altunit" => "",
                "measurement" => 6,
            ),

        "2"=> array        (
                "id" => 4,
                "altunit" => "%",
                "measurement" => "",
            ),

        "3"=> array        (
                "id" => 5,
                "altunit" => "",
                "measurement" => 4,
            ),

        "4"=> array        (
                "id" => 6,
                "altunit" => "",
                "measurement" => 6,
            )

    );

print_r( remove_dup($array, array('altunit','measurement') ) );


?>

Output

[akshay@localhost tmp]$ php test.php 
Array
(
    [0] => Array
        (
            [id] => 2
            [altunit] => %
            [measurement] => 
        )

    [1] => Array
        (
            [id] => 3
            [altunit] => 
            [measurement] => 6
        )

)

Comments

0

What you really want is a set, not an array. So if you can't fix the way you're building the array in the first place (my guess is this came from an SQL query, which would be a lot less code to rectify) you have two options for creating mapped sets in PHP.

  1. You could use SplObjectStorage
  2. You could use an Array with the key as a serialized representation of the set

The first approach would look something like this...

$set = new SplObjectStorage();

$arr = [
    0 => [
        'id'          => '2',
        'altunit'     => '%',
        'measurement' => NULL,
    ],
    1 => [
        'id'          => '3',
        'altunit'     => NULL,
        'measurement' => '6',
    ],
    2 => [
        'id'          => '4',
        'altunit'     => NULL,
        'measurement' => '6',
    ],
    3 => [
        'id'          => '5',
        'altunit'     => NULL,
        'measurement' => '6',
    ],
    4 => [
        'id'          => '6',
        'altunit'     => NULL,
        'measurement' => '6',
    ],
];

foreach($arr as $part) {
    if (isset($part['altunit'])) { // ignore if blank
        $key = (object) $part;
        $set->attach($key); // attach the set
    }
}

// Now you have...
foreach($set as $value) {
    var_dump($value);
}

This would give you...

object(stdClass)#2 (3) {
  ["id"]=>
  string(1) "2"
  ["altunit"]=>
  string(1) "%"
  ["measurement"]=>
  NULL
}

The second approach, using an array, where the array key represents a serialized version of the set would look something like this...

$set = [];

$arr = [
    0 => [
        'id'          => '2',
        'altunit'     => '%',
        'measurement' => NULL,
    ],
    1 => [
        'id'          => '3',
        'altunit'     => NULL,
        'measurement' => '6',
    ],
    2 => [
        'id'          => '4',
        'altunit'     => NULL,
        'measurement' => '6',
    ],
    3 => [
        'id'          => '5',
        'altunit'     => NULL,
        'measurement' => '6',
    ],
    4 => [
        'id'          => '6',
        'altunit'     => NULL,
        'measurement' => '6',
    ],
];

foreach($arr as $part) {
    if (isset($part['altunit'])) { // ignore if blank
        $key = "{$part['altunit']}\0{$part['measurement']}";
        $set[$key] = $part; // attach the set
    }
}

// Now you have...
foreach($set as $value) {
    var_dump($value);
}

And that would give you...

array(3) {
  ["id"]=>
  string(1) "2"
  ["altunit"]=>
  string(1) "%"
  ["measurement"]=>
  NULL
}

N.B

But, if this is a result set from an SQL query it's quite possible you could just more effectively eliminate the de-duplication process entirely by modifying the query to use WHERE NOT NULL and GROUP BY clauses instead.

Comments

0
You can try this also
 <?php
      $keys    = array_map(function ($i) { return $i; }, $array);
      $dumparr = array_combine($keys, $array);
      $result  = array_values($deduped);
      print_r($result);
?>

1 Comment

What it does basically ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.