How to get final unique array result from multiple array?
I have an array like this:
Array
(
[0] => Array
(
[0] => 8
[1] => 9
[2] => 7
)
[1] => Array
(
[0] => 7
[1] => 8
[2] => 9
[3] => 33
[4] => 21
)
[2] => Array
(
[0] => 11
[1] => 12
[2] => 33
[3] => 21
[4] => 9
[5] => 31
)
)
Expected result:
Array(
[0] => 7
[1] => 8
[2] => 9
[3] => 33
[4] => 21
[5] => 11
[6] => 12
[7] => 31
)
How to do that using php?
In your desired output indexes are same, you never achieve that. because same indexes are over-written by most recent values.
You can get like below:-
$final_array = array_unique(call_user_func_array('array_merge', $array)); //convert multi-dimensional array to single dimensional and remove duplicates
asort($final_array); // sort by value. this is optional
$final_array = array_values($final_array); // re-index final array and this is optional too
echo "<pre/>";print_r($final_array); // print final array
Output:- https://eval.in/752750
This takes three core PHP functions, sort, array_merg, and array_unique:
sort - sorts an array sent in by reference, meaning rather than returning a variable, it changes the order of the array itself.
array_merg - when combines with call_user_func_array will dynamically combine all the arrays together, however many there are.
array_unique - make sure there is only one of each element.
<?php
$arr = [ [8,9,7], [7,8,9,33,21], [11,12,33,21,9,31] ];
$merged = array_unique(call_user_func_array('array_merge', $arr));
sort($merged);
print_r($merged);
?>
Output:
Array
(
[0] => 7
[1] => 8
[2] => 9
[3] => 11
[4] => 12
[5] => 21
[6] => 31
[7] => 33
)
And here's it inside of eval.in:
https://eval.in/752793
This the way
<?php
$arr = [ [8,9,7], [7,8,9,33,21], [11,12,33,21,9,31] ];
$final = array();
foreach($arr as $child){
foreach($child as $value){
$final[] = $value;
}
}
$final = array_unique($final);
print_r($final);
?>
Demo : https://eval.in/752766
Output :
Array
(
[0] => 8
[1] => 9
[2] => 7
[6] => 33
[7] => 21
[8] => 11
[9] => 12
[13] => 31
)
Method #1: foreach loops with isset() that sort values by their first occurrence (Demo)(*this method seems to be the fastest of all)
$array=[[8,9,7],[7,8,9,33,21],[11,12,33,21,9,31]];
foreach($array as $sub){
foreach($sub as $v){
if(!isset($result[$v])){ // only add first occurence of a value
$result[$v]=$v;
}
}
}
var_export(array_values($result)); // re-index and print to screen
// condensed output: array(8,9,7,33,21,11,12,31)
Method #2: assign temporary keys which force value-overwriting to ensure no duplicates (Demo)
$array=[[8,9,7],[7,8,9,33,21],[11,12,33,21,9,31]];
foreach($array as $sub){
foreach($sub as $v){
$result[$v]=$v; // force overwrite because duplicate keys cannot occur
}
}
sort($result); // sort and re-index
var_export($result); // print to screen
// condensed output: array(7,8,9,11,12,21,31,33)
Method #3: array_merge() with splat operator and array_unique() (Demo)
$array=[[8,9,7],[7,8,9,33,21],[11,12,33,21,9,31]];
$unique=array_unique(array_merge(...$array)); // merge all subarrays
sort($unique); // sort and re-index
var_export($unique); // print to screen
// condensed output: array(7,8,9,11,12,21,31,33)
Method #4: unorthodox json_encode() & preg_match_all() (Demo) (Pattern Demo)
$array=[[8,9,7],[7,8,9,33,21],[11,12,33,21,9,31]];
$unique=preg_match_all('~\b(\d+)\b(?!.*\b\1\b)~',json_encode($array),$out)?$out[0]:[];
sort($unique); // sort and re-index
var_export($unique); // print to screen
// condensed output: array(7,8,9,11,12,21,31,33)
I need to pass multiple array's in an indexed format to a cartesain function in order to calculate every permutation. This works when the code is:
$count = cartesian(
Array("GH20"),
Array(1,3),
Array(6,7,8),
Array(9,10)
);
I will not always know the length, number of arrays, or values so they are stored in another array "$total" which may look something like this:
Array (
[0] => Array
(
[0] => 1
[1] => 3
)
[1] => Array
(
[0] => 6
[1] => 7
[2] => 8
)
[2] => Array
(
[0] => 9
[1] => 10
)
)
I have tried implementing the user_call_back_function as per:
$count = call_user_func('cartesian', array($total));
However the array that then gets passed looks like this:
Array (
[0] => Array (
[0] => Array (
[0] => Array (
[0] => 1
[1] => 3
[2] => 4
)
[1] => Array (
[0] => 5
[1] => 6
[2] => 7
[3] => 8
)
[2] => Array (
[0] => 9
[1] => 10
)
)
)
)
Where am I going wrong, why is the array being buried further down in dimensions where it is not needed, and is this the reason why my cartesain function does no longer work?
Thanks, Nick
As requested, here is my cartesain function:
function cartesian() {
$_ = func_get_args();
if(count($_) == 0)
return array(array());
$a = array_shift($_);
$c = call_user_func_array(__FUNCTION__, $_);
$r = array();
foreach($a as $v)
foreach($c as $p)
$r[] = array_merge(array($v), $p);
return $r;
}
why is the array being buried further down in dimensions where it is not needed?
Simply because you are wrapping an array in another array when calling call_user_func.
$count = call_user_func('cartesian', array($total));
Perhaps you meant this:
$count = call_user_func('cartesian', $total);
is this the reason why my cartesain function does no longer work?
I don't know, you have not posted your cartesain, just an arrat called cartesain
EDIT as op updated the question.
If you are using PHP 5.6 you should be able to use the splat operator.
call_user_func("cartesain", ...$total);
Disclaimer, I have not tested this.
Arrays and Traversable objects can be unpacked into argument lists when calling functions by using the ... operator.
my array is
Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 4
[5] => 5
[6] => 6
)
start value is = 3
Array
(
[0] => 3
[1] => 4
[2] => 5
[3] => 6
[4] => 0
[5] => 1
[6] => 2
)
any idea friends..
try
$arr = array(0,1,2,3,4,5,6);
foreach($arr as $k=>$v) {
if($v >= 3)
$a[] = $v;
else
$b[] = $v;
}
$c = array_merge($a, $b);
print_r($c); //Array ( [0] => 3 [1] => 4 [2] => 5 [3] => 6 [4] => 0 [5] => 1 [6] => 2 )
Step 0 (optional if needed):
order the array (heap or some other sort algorithm)
Step 1:
create an output array
Step 2:
loop trough the array and find your start point move the value and the ones after to new array and set the value in the original array to null
Step 3:
loop trough the array and move the remaining values over
DONE
Just do this:
Call asort on the array.
Call array_search to find the index you want to slice.
Call array_slice to cut off the part you want.
Call array_merge to merge them in the right order.
I don't know PHP that well but a quick look at php.net and I suspect this will work.
Seeing how your array is already sorted and 0-indexed, you can just slice and reorganise it:
array_values(array_slice($arr, 3, null, true) + array_slice($arr, 0, 3, true));
I want to search an array for duplicate values in each subarray and if there is one, only keep the highest value connected to this item.
That's my question, but I love to add an example to clarify things!
This is my array:
Array
(
[0] => Array
(
[groupid] => 1
[points] => 5
)
[1] => Array
(
[groupid] => 1
[points] => 1
)
[2] => Array
(
[groupid] => 1
[points] => 4
)
[3] => Array
(
[groupid] => 2
[points] => 1
)
)
As you can see, the first three items have the same groupid. I want to match those items and see which of them has the highest points. The other one (with the lowest points) should be kicked out of the array.
So in this case, item 0, 1 and 2 are from the same group, but 2 has the highest points. 0 and 1 should be dropped out of the array.
My desired result would be something like this:
Array
(
[0] => Array
(
[groupid] => 1
[points] => 5
)
[1] => Array
(
[groupid] => 2
[points] => 1
)
)
I've been trying for a few hours now but no luck yet. Maybe I am overlooking something very simple and thinking to hard to figure this out... Any help would be appreciated!
EDIT
It's a Drupal site (but that shouldn't make any difference) and this is query:
foreach ($promotions as $value) {
$promo = db_query("SELECT * FROM {_promo_articles} WHERE art = :art AND promoid = :promoid", array(
':art' => $value['product'][0]->sku,
':promoid' => $value['promo_id'][0])) ->fetchAll();
}
As I see from your comment, the information is coming from the database so do something like this:
(pseudocode)
SELECT group_id, MAX(points)
FROM db_table
GROUP BY group_id;
I would do something like :
$final_array = array();
foreach($array AS $element)
{
if(!isset($final_array[$element["groupid"]]) ||
$final_array[$element["groupid"]] < $element["points"])
$final_array[$element["groupid"]] = $element["points"];
}
Then, $final_array would look like...
Array
(
[1] => 5
[2] => 1
)
(group 1 has 5 points, group 2 has 1 point)
You could use the usort function to order your array in order by points. This function will order it from greatest to least:
usort($myArray, function($a, $b) {
return $b['points'] - $a['points'];
});
As stated in comments the best way to do this is from your database if that is an option.
If not you can use array_reduce and a closure (PHP 5.3+)
$array = array_reduce($array,function(&$result, $val){
if (!array_key_exists($val["groupid"], $result){
$result[$val["groupid"]] = $val;
} else {
if ($result[$val["groupid"]]["points"] < $val["points"])
$result[$val["groupid"]]["points"] = $val["points"];
}
}, array());
Then if you want to reset the keys
$array = array_values($array);
How can i make the values of such an array unique.
Array ( [0] => Array ( [0] => wallet [1] => pen [2] => perfume [3] => pen) )
as there is pen twice i would like it to be deleted in this way :
( [0] => Array ( [0] => wallet [1] => pen [2] => perfume) )
OR
( [0] => Array ( [0] => wallet [1] => perfume [2] => pen) )
and i would like it to apply for any length.
thanks for your help
How about array_flip used twice:
$arr = Array(0 => wallet, 1 => pen, 2 => perfume, 3 => pen);
$arr = array_flip(array_flip($arr));
print_r($arr);
output:
Array
(
[0] => wallet
[3] => pen
[2] => perfume
)
If you want to renumbered the indexes, add this ligne after:
$arr = array_values($arr);
if you just want to select a unique value you need to pass the array that you want to compare the values, I am assuming you passed the main array, you need to pass the array where the problem is found which is in your case the index 0 of an array
$result = array_unique($input[0]);
$input will have an array of unique values so pen will not be 2
if you need to delete any duplicated values in the array you can do this.
$input[0] = array_unique($input[0]);
if you need to reset the index you can use this
$new_index = array_values($input[0]);
print_r($new_index);
$tmp = array ();
foreach ($array as $row)
array_push($tmp,array_unique($row));
Here is the solution for multi dimensopnal array
$res = array();
foreach($your_array as $key=>$val){
$res[$key] = array_unique($val);
}
echo "<pre>";
print_r($res);