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);
3
  • How do you know which one to keep? Commented Dec 23, 2014 at 7:58
  • Create a new array : array_tmp() and insert using array_push() with comparing number and location. Commented Dec 23, 2014 at 8:08
  • This question is a loose version of stackoverflow.com/questions/27526145/… Commented Dec 23, 2014 at 13:04

4 Answers 4

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
Sign up to request clarification or add additional context in comments.

1 Comment

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.
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 ) )

3 Comments

How does this return unique Number and Location when you're calling array_unique on the Qty?
Your result has two elements with Number => L1, Location => Location-B.
array_intersect_key(), array_unique() and array_map(): loop over the array 3 times while a single pass is enough. No good.
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"
    }
}

2 Comments

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.
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 :)
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

Comments

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.