Unset associative array by value - php

I'd like to remove an array item by value. Key cannot be specified. Here is the array. I have sorted the array by value, numeric descending.
Array
(
[this] => 15
[that] => 10
[other] => 9
[random] => 8
[keys] => 4
)
If I want to unset all items that have a value less than 10. How do I do that?

Use the array_filter function:
$a = array_filter($a, function($x) { return !($x < 10); });

$test = array(
"this" => 15,
"that" => 10,
"other" => 9,
"random" => 8,
"keys" => 4
);
echo "pre: ";print_r($test);
pre: Array ( [this] => 15 [that] => 10 [other] => 9 [random] => 8 [keys] => 4 )
Run this code:
foreach($test AS $key => $value) {
if($value <= 10) {
unset($test[$key]);
}
}
Results are:
echo "post: ";print_r($test);
post: Array ( [this] => 15 )

foreach($array as $key => $value)
if( $value < 10 )
unset($array[$key])

Assuming that all values are ints:
for (i=9;i>=0;i--)
{
while (array_search($i, $assocArray) !== false)
{
unset($assocArray[array_search($i, $assocArray)]);
}
}
There probably are more elegant ways of doing this, but fever has a firm grip on my brain :)
knittl's answer is correct, but if you're using an older version of PHP, you can' t use the anonymous function, just do:
function filterFunc($v)
{
return $v >= 10;
}
$yourArray = array_filter($yourArray,'filterFunc');
Credit to Knittl

Related

Remove element from multidimensional indexed array by value using PHP

I have array:
Array
(
[5] => Array
(
[0] => 19
[1] => 18
)
[6] => Array
(
[0] => 28
)
)
And I'm trying to delete element by value using my function:
function removeElementWithValue($obj, $delete_value){
if (!empty($obj->field)) {
foreach($obj->field as $key =>$value){
if (!empty($value)) {
foreach($value as $k=>$v){
if($v == $delete_value){
$obj->field[$key][$k] = '';
}
}
}
}
}
return urldecode(http_build_query($obj->field));
}
echo removeElementWithValue($request, '19');
After operation above I have: 5[0]=&5[1]=18&6[0]=28; // Right!!!
echo removeElementWithValue($request, '18');
After operation above I have: 5[0]=&5[1]=&6[0]=28; // Wrong ???
But my expected result after second operation is:
5[0]=19&5[1]=&6[0]=28;
Where is my mistake?
Thanks!
Use array_walk_recursive to find and change value
$arr = Array (
5 => Array ( 0 => 19, 1 => 18 ),
6 => Array ( 0 => 28));
$value = 18;
array_walk_recursive($arr,
function (&$item, $key, $v) { if ($item == $v) $item = ''; }, $value);
print_r($arr);
result:
Array (
5 => Array ( 0 => 19, 1 => ),
6 => Array ( 0 => 28));
A simpler function might be..
function removeElementWithValue($ar,$val){
foreach($ar as $k=>$array){
//update the original value with a new array
$new_ar = array_diff_key($array,array_flip(array_keys($array,$val)));
if($new_ar){
$ar[$k]=$new_ar;
}else{
unset($ar[$k]);//or remove the empty value
}
}
return $ar;
}

Extract negative and non-negative values from an array

I need to divide an array into two arrays.
One array will contain all positive values (and zeros), the other all negative values.
Example array:
$ts = [7,-10,13,8,0,4,-7.2,-12,-3.7,3.5,-9.6,6.5,-1.7,-6.2,7];
Negatives result array:
[-10,-7.2,-12,-3.7,-9.6,-1.7,-6.2];
Non-negatives result array:
[7,13,8,0,4,3.5,6.5,7];
Without using any array functions..
Pretty straightforward. Just loop through the array and check if the number is less than 0, if so , push it in the negative array else push it in the positive array.
<?php
$ts=array(7,-10,13,8,4,-7.2,-12,-3.7,3.5,-9.6,6.5,-1.7,-6.2,7);
$pos_arr=array(); $neg_arr=array();
foreach($ts as $val)
{
($val<0) ? $neg_arr[]=$val : $pos_arr[]=$val;
}
print_r($pos_arr);
print_r($neg_arr);
OUTPUT :
Array
(
[0] => 7
[1] => 13
[2] => 8
[3] => 4
[4] => 3.5
[5] => 6.5
[6] => 7
)
Array
(
[0] => -10
[1] => -7.2
[2] => -12
[3] => -3.7
[4] => -9.6
[5] => -1.7
[6] => -6.2
)
You can use array_filter function,
$positive = array_filter($ts, function ($v) {
return $v > 0;
});
$negative = array_filter($ts, function ($v) {
return $v < 0;
});
Note: This will skip values with 0, or you can just change condition to >=0 in positive numbers filter to considered in positive group.
DEMO.
The most elegant is to use phps array_filter() function:
<?php
$ts = [ 7,-10,13,8,4,-7.2,-12,-3.7,3.5,-9.6,6.5,-1.7,-6.2,7 ];
print_r( array_filter( $ts, function( $val ) { return (0>$val); } ) );
print_r( array_filter( $ts, function( $val ) { return ! (0>$val); } ) );
?>
If you are still using an older php version you need some longer implementation:
<?php
$ts = array( 7,-10,13,8,4,-7.2,-12,-3.7,3.5,-9.6,6.5,-1.7,-6.2,7 );
print_r( array_filter( $ts, create_function( '$val', 'return (0>$val);' ) ) );
print_r( array_filter( $ts, create_function( '$val', 'return ! (0>$val);' ) ) );
?>
Food for thought, you could write a generic function that splits an array based on a boolean result:
// splits an array based on the return value of the given function
// - add to the first array if the result was 'true'
// - add to the second array if the result was 'false'
function array_split(array $arr, callable $fn)
{
$a = $b = [];
foreach ($arr as $key => $value) {
if ($fn($value, $key)) {
$a[$key] = $value;
} else {
$b[$key] = $value;
}
}
return [$a, $b];
}
list($positive, $negative) = array_split($ts, function($item) {
return $item >= 0;
});
print_r($positive);
print_r($negative);
Demo
Rather than declaring two arrays, I recommend declaring one array with two subarrays. You can either give the subarrays an index of 0 or 1 depending on the conditional evaluation with zero, or you can go a little farther by declaring a lookup array to replace the integer key with an expressive word.
Regardless of if you choose to create one array or two arrays, you should only make one loop over the input array. Making two loops or by calling array_filter() twice is needlessly inefficient.
Code: (Demo)
$ts = [7,-10,13,8,4,-7.2,-12,-3.7,3.5,-9.6,6.5,-1.7,-6.2,7];
const KEY_NAMES = [0 => 'negative', 1 => 'non-negatuve'];
$result = [];
foreach ($ts as $v) {
$result[KEY_NAMES[$v >= 0]][] = $v;
}
var_export($result);
Output:
array (
'non-negatuve' =>
array (
0 => 7,
1 => 13,
2 => 8,
3 => 4,
4 => 3.5,
5 => 6.5,
6 => 7,
),
'negative' =>
array (
0 => -10,
1 => -7.2,
2 => -12,
3 => -3.7,
4 => -9.6,
5 => -1.7,
6 => -6.2,
),
)

PHP Sorting Multidimensional Array Sorted by Weight

I just asked this question a moment ago but I asked incorrectly so I apologize.
I'm hoping there's an easy way to do this without tons and tons of loops.
I have a matrix in the following manner:
Foo1 Foo2 Foo3 .... FooN
Jan 1 8 5 4
Feb 10 12 15 11
Mar 12 7 4 3
Apr 10 16 7 17
Assuming the following array:
$arrayMonths = array(
'jan' => array(1, 8, 5,4)
'feb' => array(10,12,15,11)
'mar' => array(12, 7, 4, 3)
'apr' => array(10,16,7,17)
);
I need to sort the above array and show it in the following manner:
array[apr][FooN] = 17
array[feb][Foo3] = 15
array[mar][Foo1] = 12
array[jan][Foo2] = 8
Essentially, I need to get the greatest sum of the above weights, one month can only have one foo and one foo can only have one month. In the above example, the result would be 52.
Thanks
See Demo : http://codepad.org/vDI2k4n6
$arrayMonths = array(
'jan' => array(1, 8, 5,4),
'feb' => array(10,12,15,11),
'mar' => array(12, 7, 4, 3),
'apr' => array(10,16,7,17),
);
$position = array("Foo1","Foo2","Foo3","FooN");
$set = array();
foreach($arrayMonths as $key => $value)
{
$max = max($value);
$pos = array_search($max, $value);
$set[$key][$position[$pos]] = $max ;
}
function cmp($a, $b)
{
foreach($a as $key => $value )
{
foreach ($b as $bKey => $bValue)
{
return $bValue - $value ;
}
}
}
uasort($set,"cmp");
var_dump($set);
Output
array
'apr' =>
array
'FooN' => int 17
'feb' =>
array
'Foo3' => int 15
'mar' =>
array
'Foo1' => int 12
'jan' =>
array
'Foo2' => int 8
$totalArr = array();
$total = 0;
foreach($arrayMonths as $month => $row)
{
$high = max($row);
$totalArr[$month]['foo'] = $high;
$total += $high;
}
echo "Total is: " . $total . "\n\n";
print_r($totalArr);
Outputs:
Total is: 52
Array
(
[jan] => Array
(
[foo] => 8
)
[feb] => Array
(
[foo] => 15
)
[mar] => Array
(
[foo] => 12
)
[apr] => Array
(
[foo] => 17
)
)
Use uasort() if you want to sort the new array.
http://php.net/manual/en/function.uasort.php
The PHP function max() is the key here:
$sum = 0;
foreach ($array as $row) {
$sum += max($row);
}
echo $sum;
Look into this way of doing it.
http://www.php.net/manual/en/function.uasort.php
Input the array and a reference to a comparison function that you write yourself.
$arr_new = array();
foreach(array_keys($arrayMonths) as $h) {
$int_max = max($arrayMonths[$h]);
foreach(array_keys($arrMonths[$h]) as $h2)
if ($arrMonths[$h][$h2] == $int_max) {
$arr_new[$h]["foo{$h2}"] = $int_max;
break;
}
}

parsing out the last number of the post

Ok so i have a post that looks kind of this
[optional_premium_1] => Array
(
[0] => 61
)
[optional_premium_2] => Array
(
[0] => 55
)
[optional_premium_3] => Array
(
[0] => 55
)
[premium_1] => Array
(
[0] => 33
)
[premium_2] => Array
(
[0] => 36 )
[premium_3] => Array
(
[0] => 88 )
[premium_4] => Array
(
[0] => 51
)
how do i get the highest number out of the that. So for example, the optional "optional_premium_" highest is 3 and the "premium_" optional the highest is 4. How do i find the highest in this $_POST
You could use array_key_exists(), perhaps something like this:
function getHighest($variableNamePrefix, array $arrayToCheck) {
$continue = true;
$highest = 0;
while($continue) {
if (!array_key_exists($variableNamePrefix . "_" . ($highest + 1) , $arrayToCheck)) {
$continue = false;
} else {
highest++;
}
}
//If 0 is returned than nothing was set for $variableNamePrefix
return $highest;
}
$highestOptionalPremium = getHighest('optional_premium', $_POST);
$highestPremium = getHighest('premium', $_POST);
I have 1 question with 2 parts before I answer, and that is why are you using embedded arrays? Your post would be much simpler if you used a standard notation like:
$_POST['form_input_name'] = 'whatever';
unless you are specifically building this post with arrays for some reason. That way you could use the array key as the variable name and the array value normally.
So given:
$arr = array(
"optional_premium_1" => "61"
"optional_premium_2" => "55"
);
you could use
$key = array_keys($arr);
//gets the keys for that array
//then loop through get raw values
foreach($key as $val){
str_replace("optional_premium_", '', $val);
}
//then loop through again to compare each one
$highest = 0;
for each($key as $val){
if ((int)$val > $highest) $highest = (int)$val;
}
that should get you the highest one, but then you have to go back and compare them to do whatever your end plan for it was.
You could also break those into 2 separate arrays and assuming they are added in order just use end() http://php.net/manual/en/function.end.php
Loop through all POST array elements, pick out elements having key names matching "name_number" pattern and save the ones having the largest number portion of the key names. Here is a PHP script which does it:
<?php // test.php 20110428_0900
// Build temporary array to simulate $_POST
$TEMP_POST = array(
"optional_premium_1" => array(61),
"optional_premium_2" => array(55),
"optional_premium_3" => array(55),
"premium_1" => array(33),
"premium_2" => array(36),
"premium_3" => array(88),
"premium_4" => array(51),
);
$names = array(); // Array of POST variable names
// loop through all POST array elements
foreach ($TEMP_POST as $k => $v) {
// Process only elements with names matching "word_number" pattern.
if (preg_match('/^(\w+)_(\d+)$/', $k, $m)) {
$name = $m[1];
$number = (int)$m[2];
if (!isset($names[$name]))
{ // Add new POST var key name to names array
$names[$name] = array(
"name" => $name,
"max_num" => $number,
"key_name" => $k,
"value" => $v,
);
} elseif ($number > $names[$name]['max_num'])
{ // New largest number in key name.
$names[$name] = array(
"name" => $name,
"max_num" => $number,
"key_name" => $k,
"value" => $v,
);
}
}
}
print_r($names);
?>
Here is the output from the script:
Array
(
[optional_premium] => Array
(
[name] => optional_premium
[max_num] => 3
[key_name] => optional_premium_3
[value] => Array
(
[0] => 55
)
)
[premium] => Array
(
[name] => premium
[max_num] => 4
[key_name] => premium_4
[value] => Array
(
[0] => 51
)
)
)
Though ineffective, you could try something like
$largest = 0;
foreach($_POST as $key => $value)
{
$len = strlen("optional_premium_");
$num = substr($key, $len);
if($num > $largest)
$largest = $num;
}
print_r($largest);
The problem being that this will only work for one set of categories. It will most likely give errors throughout the script.
Ideally, you would want to reorganize your post, make each array be something like
[optional_premium_1] => Array
(
[0] => 61
["key"] => 1
)
[optional_premium_2] => Array
(
[0] => 61
["key"] => 2
)
Then just foreach and use $array["key"] to search.

PHP Need to recursively reverse an array

I need to recursively reverse a HUGE array that has many levels of sub arrays, and I need to preserve all of the keys (which some are int keys, and some are string keys), can someone please help me? Perhaps an example using array_reverse somehow? Also, is using array_reverse the only/best method of doing this?
Thanks :)
Try this:
function array_reverse_recursive($arr) {
foreach ($arr as $key => $val) {
if (is_array($val))
$arr[$key] = array_reverse_recursive($val);
}
return array_reverse($arr);
}
Recursively:
<?php
$a = array(1,3,5,7,9);
print_r($a);
function rev($a) {
if (count($a) == 1)
return $a;
return array_merge(rev(array_slice($a, 1, count($a) - 1)), array_slice($a, 0, 1));
}
$a = rev($a);
print_r($a);
?>
output:
Array
(
[0] => 1
[1] => 3
[2] => 5
[3] => 7
[4] => 9
)
Array
(
[0] => 9
[1] => 7
[2] => 5
[3] => 3
[4] => 1
)
Reversing a HUGE php array in situ (but not recursively):
function arrayReverse(&$arr){
if (!is_array($arr) || empty($arr)) {
return;
}
$rev = array();
while ( false !== ( $val = end($arr) ) ){
$rev[ key($arr) ] = $val;
unset( $arr[ key($arr) ] );
}
$arr = $rev;
}
//usage
$test = array(5, 'c'=>100, 10, 15, 20);
arrayReverse($test);
var_export($test);
// result: array ( 3 => 20, 2 => 15, 1 => 10, 'c' => 100, 0 => 5, )

Categories