0

I have an array structure like this

  [0]=>array(3) {
    ["Number"]=> "L1"
    ["Location"]=> "Location-A"
    ["Qty"]=>"1"
  }
  [1]=>array(3) {
    ["Number"]=> "L1"
    ["Location"]=> "Location-B"
    ["Qty"]=> "5"
  }
  [2]=> array(3) {
    ["Number"]=> "L1"
    ["Location"]=> "Location-B"
    ["Qty"]=> "4"
  }
  [3]=>array(3) {
    ["Number"]=> "L2"
    ["Location"]=>  "Location-B"
    ["Qty"]=>  "5"
  }

But i required below structure as ouput

 [0]=>array(3) {
    ["Number"]=> "L1"
    ["Location"]=> "Location-A"
    ["Qty"]=>"1"
  }
  [1]=> array(3) {
    ["Number"]=> "L1"
    ["Location"]=> "Location-B"
    ["Qty"]=> "4"
  }
  [2]=>array(3) {
    ["Number"]=> "L2"
    ["Location"]=>  "Location-B"
    ["Qty"]=>  "5"
  }

How can i remove duplicate value by Number and Location?

ksort only works for one value, i need to remove by two values , how can i achieve this PHP ?

$ordered = array();
foreach ($data as $da) 
{           
    $ordered[$da['Number']] = $da;
    $ordered[$da['Location']] = $da;            
}
ksort($ordered);
Silviaa
  • 475
  • 8
  • 35
  • How do you know which one to keep? – RST Dec 23 '14 at 07:58
  • Create a new array : `array_tmp()` and insert using `array_push()` with comparing number and location. – EngineerCoder Dec 23 '14 at 08:08
  • This question is a loose version of http://stackoverflow.com/questions/27526145/delete-duplicate-on-multidimensional-array-and-take-those-having-highest-value-i – axiac Dec 23 '14 at 13:04

4 Answers4

1

Concatenate the two fields when creating your new array:

foreach ($data as $da) {
    $result[$da['Number'] . '.' . $da['Location']] = $da;
}
$result = array_values($result); // Turn it back into indexed array
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    It keeps the last value from `$data` for each pair of `'Number'` and `'Location'`. Since the OP didn't mention which value should be kept for duplicates this solution is OK. – axiac Dec 23 '14 at 12:54
1

Try this..

 <?php
    $array = array(
        0 => array('Number'=>'L1','Location'=>'Location-A','Qty'=>'1'),
        1 => array('Number'=>'L1','Location'=>'Location-B','Qty'=>'5'),
        2 => array('Number'=>'L1','Location'=>'Location-B','Qty'=>'4'),
        3 => array('Number'=>'L2','Location'=>'Location-B','Qty'=>'5'),
    );
    $output =   array_values(array_intersect_key($array,array_unique(array_map(function($arrayval) {
        return $arrayval['Number'] . '.' .$arrayval['Location'];
    }, $array))
));
    print_r($output);

Output

Array ( [0] => Array ( [Number] => L1 [Location] => Location-A [Qty] => 1 )
        [1] => Array ( [Number] => L1 [Location] => Location-B [Qty] => 5 ) 
        [2] => Array ( [Number] => L2 [Location] => Location-B [Qty] => 5 ) )
Deenadhayalan Manoharan
  • 5,436
  • 14
  • 30
  • 50
  • How does this return unique `Number` and `Location` when you're calling `array_unique` on the `Qty`? – Barmar Dec 23 '14 at 08:05
  • Your result has two elements with `Number => L1, Location => Location-B`. – Barmar Dec 23 '14 at 08:07
  • `array_intersect_key()`, `array_unique()` and `array_map()`: loop over the array 3 times while a single pass is enough. No good. – axiac Dec 23 '14 at 12:58
0

Try this:

function array_unique_c($array, Closure $comparer) {
    $result = array();
    for($i = 0; $i < count($array); $i++) {
        $duplicates = false;
        for($n = $i + 1; $n < count($array); $n++) {
            if ($comparer($array[$i], $array[$n])) {
                $duplicates = true;
                break;
            }
        }
        if(!$duplicates) {
            $result[] = $array[$i];
        }
    }

    return $result;
}

Usage:

$uniqueArray = array_unique_c($a, function ($itemA, $itemB) {
    return $itemA['Number'] == $itemB['Number'] && $itemA['Location'] == $itemB['Location'];
});

Output:

array(3) {
    [0] => array(3) {
        ["Number"] => string(2) "L1"
        ["Location"] => string(10) "Location-A"
        ["Qty"] => string(1) "1"
    }
    [1] => array(3) {
        ["Number"]=> string(2) "L1"
        ["Location"]=> string(10) "Location-B"
        ["Qty"]=> string(1) "4"
    }
    [2]=> array(3) {
        ["Number"]=> string(2) "L2"
        ["Location"]=> string(10) "Location-B"
        ["Qty"]=> string(1) "5"
    }
}
  • The code is too complicated (difficult to understand) and the performance is poor because of the inner loop. A single loop through the array is enough to fulfill the request. – axiac Dec 23 '14 at 12:57
  • Yes, the accepted answer is enough to fulfill the request, but I just tried to provide a more abstract solution that could be used in many more cases :) – Vytautas Lozickas Dec 31 '14 at 00:16
0

Easy way to do this job:

$data = [
    ["Number"=> "L1","Location"=> "Location-A","Qty"=>"1"],
    ["Number"=> "L2","Location"=> "Location-B","Qty"=>"6"],
    ["Number"=> "L3","Location"=> "Location-A","Qty"=>"8"],
    ["Number"=> "L2","Location"=> "Location-B","Qty"=>"5"],
    ["Number"=> "L3","Location"=> "Location-A","Qty"=>"2"],
    ["Number"=> "L1","Location"=> "Location-B","Qty"=>"4"],
    ["Number"=> "L1","Location"=> "Location-B","Qty"=>"1"],
    ["Number"=> "L2","Location"=> "Location-B","Qty"=>"3"],
];

foreach ($data as $k=>$v) {
    $arr[md5($v['Number'].$v['Location'])] = $v;
}

$result = array_values($arr); //can be omitted

As you can see $arr is equal $result and you can ommit array_values() func

Arthur Veselov
  • 1,167
  • 10
  • 9