Grab a part on array (inside array) PHP - php

I need to grab data within array (inside array) that will grab only the second and the third rows of each line.
<?php
$salaries = array(
//I WANT TO MAKE A NEW ARRAY FROM ALL THE SECOND AND THE THIRD ROWS
"a" => 2000, 1500, 3000, 1950
"b" => 1000, 2300, 2233, 2400
"c" => 500 , 6590, 1024, 2048
//FOR EXAMPLE RESULTS IN THIS CASE WOULD BE :
//$newarray = array(1500,3000,2300,2233,6590,2048);
);
?>
If there is no direct command for that loops would be fine :)
Thanks !

First of all, your array declaration isn't syntactically valid.
If you meant it to be a multi-dimensionl array as follows:
$salaries = array(
"a" => array(2000, 1500, 3000, 1950),
"b" => array(1000, 2300, 2233, 2400),
"c" => array(500 , 6590, 1024, 2048)
);
Then, this can be done using two loops. In the first loop, loop through all the sub-arrays. Loop through the values in each sub-array, check if the value is second or third. If so, add it to the new array:
foreach ($salaries as $key => $arr) {
for ($i=0; $i < count($arr); $i++) {
if ($i == 1 || $i == 2) {
$result[$key][] = $arr[$i];
}
}
}
print_r($result);
Demo
For completeness, I'm going to add the solution for the case when the values are comma-separated strings, not arrays:
$salaries = array(
"a" => '2000, 1500, 3000, 1950',
"b" => '1000, 2300, 2233, 2400',
"c" => '500 , 6590, 1024, 2048'
);
The logic is exactly the same, but instead of accessing the inner array elements directly, you'll have to use explode() to create an array of the values. Then use array_slice() to get the second and third elements, and create a new array from it:
$result = array();
foreach ($salaries as $key => $value) {
$pieces = explode(', ', $value);
$slice[$key] = array_slice($pieces, 1, 2);
$result = array_merge($result, $slice);
}
Demo

Related

PHP filtering an associative array based on a value found in a subarray [duplicate]

I have an array like this:
array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2)
Now I want to filter that array by some condition and only keep the elements where the value is equal to 2 and delete all elements where the value is NOT 2.
So my expected result array would be:
array("a" => 2, "c" => 2, "f" => 2)
Note: I want to keep the keys from the original array.
How can I do that with PHP? Any built-in functions?
$fullArray = array('a'=>2,'b'=>4,'c'=>2,'d'=>5,'e'=>6,'f'=>2);
function filterArray($value){
return ($value == 2);
}
$filteredArray = array_filter($fullArray, 'filterArray');
foreach($filteredArray as $k => $v){
echo "$k = $v";
}
You somehow have to loop through your array and filter each element by your condition. This can be done with various methods.
Loops while / for / foreach method
Loop through your array with any loop you want, may it be while, for or foreach. Then simply check for your condition and either unset() the elements if they don't meet your condition or write the elements, which meet the condition, into a new array.
Looping
//while loop
while(list($key, $value) = each($array)){
//condition
}
//for loop
$keys = array_keys($array);
for($counter = 0, $length = count($array); $counter < $length; $counter++){
$key = $keys[$counter];
$value = $array[$key];
//condition
}
//foreach loop
foreach($array as $key => $value){
//condition
}
Condition
Just place your condition into the loop where the comment //condition is. The condition can just check for whatever you want and then you can either unset() the elements which don't meet your condition, and reindex the array with array_values() if you want, or write the elements in a new array which meet the condition.
//Pseudo code
//Use one of the two ways
if(condition){ //1. Condition fulfilled
$newArray[ ] = $value;
//↑ Put '$key' there, if you want to keep the original keys
//Result array is: $newArray
} else { //2. Condition NOT fulfilled
unset($array[$key]);
//Use array_values() after the loop if you want to reindex the array
//Result array is: $array
}
array_filter() method
Another method is to use the array_filter() built-in function. It generally works pretty much the same as the method with a simple loop.
You just need to return TRUE if you want to keep the element in the array and FALSE if you want to drop the element out of the result array.
//Anonymous function
$newArray = array_filter($array, function($value, $key){
//condition
}, ARRAY_FILTER_USE_BOTH);
//Function name passed as string
function filter($value, $key){
//condition
}
$newArray = array_filter($array, "filter", ARRAY_FILTER_USE_BOTH);
//'create_function()', NOT recommended
$newArray = array_filter($array, create_function('$value, $key', '/* condition */'), ARRAY_FILTER_USE_BOTH);
preg_grep() method
preg_grep() is similar to array_filter() just that it only uses regular expression to filter the array. So you might not be able to do everything with it, since you can only use a regular expression as filter and you can only filter by values or with some more code by keys.
Also note that you can pass the flag PREG_GREP_INVERT as third parameter to invert the results.
//Filter by values
$newArray = preg_grep("/regex/", $array);
Common conditions
There are many common conditions used to filter an array of which all can be applied to the value and or key of the array. I will just list a few of them here:
//Odd values
return $value & 1;
//Even values
return !($value & 1);
//NOT null values
return !is_null($value);
//NOT 0 values
return $value !== 0;
//Contain certain value values
return strpos($value, $needle) !== FALSE; //Use 'use($needle)' to get the var into scope
//Contain certain substring at position values
return substr($value, $position, $length) === $subString;
//NOT 'empty'(link) values
array_filter($array); //Leave out the callback parameter
You can iterate on the copies of the keys to be able to use unset() in the loop:
foreach (array_keys($array) as $key) {
if ($array[$key] != 2) {
unset($array[$key]);
}
}
The advantage of this method is memory efficiency if your array contains big values - they are not duplicated.
EDIT I just noticed, that you actually only need the keys that have a value of 2 (you already know the value):
$keys = array();
foreach ($array as $key => $value) {
if ($value == 2) {
$keys[] = $key;
}
}
This should work, but I'm not sure how efficient it is as you probably end up copying a lot of data.
$newArray = array_intersect_key(
$fullarray,
array_flip(array_keys($fullarray, 2))
);
This can be handled using a closure. The following answer is inspired by PHP The Right Way:
//This will create an anonymous function that will filter the items in the array by the value supplied
function cb_equal_to($val)
{
return function($item) use ($val) {
return $item == $val;
};
}
$input = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
// Use array_filter on a input with a selected filter function
$filtered_array = array_filter($input, cb_equal_to(2));
Contents of $filtered_array would now be
array ( ["a"] => 2 ["c"] => 2 ["f"] => 2 )
I think the snappiest, readable built-in function is: array_intersect()
Code: (Demo)
$array = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
var_export(array_intersect($array, [2]));
Output:
array (
'a' => 2,
'c' => 2,
'f' => 2,
)
Just make sure you declare the 2nd parameter as an array because that is the value type expected.
Now there is nothing wrong with writing out a foreach loop, or using array_filter(), they just have a more verbose syntax.
array_intersect() is also very easy to extend (include additional "qualifying" values) by adding more values to the 2nd parameter array.
From PHP7.4, arrow function syntax is available. This affords more concise code and the ability to access global variables without use.
Code: (Demo)
$haystack = [
"a" => 2,
"b" => 4,
"c" => 2,
"d" => 5,
"e" => 6,
"f" => 2
];
$needle = 2;
var_export(
array_filter(
$haystack,
fn($v) => $v === $needle
)
);
I might do something like:
$newarray = array();
foreach ($jsonarray as $testelement){
if ($testelement == 2){$newarray[]=$testelement}
}
$result = count($newarray);
foreach ($aray as $key => $value) {
if (2 != $value) {
unset($array($key));
}
}
echo 'Items in array:' . count($array);
You can do something like:
$array = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
$arrayFiltered = array_filter($array, function ($element) {
return $element == 2;
});
or:
$arrayFiltered = array_filter($array, fn($element) => $element == 2);

How to exclude array, when sub array contain specific value [duplicate]

I have an array like this:
array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2)
Now I want to filter that array by some condition and only keep the elements where the value is equal to 2 and delete all elements where the value is NOT 2.
So my expected result array would be:
array("a" => 2, "c" => 2, "f" => 2)
Note: I want to keep the keys from the original array.
How can I do that with PHP? Any built-in functions?
$fullArray = array('a'=>2,'b'=>4,'c'=>2,'d'=>5,'e'=>6,'f'=>2);
function filterArray($value){
return ($value == 2);
}
$filteredArray = array_filter($fullArray, 'filterArray');
foreach($filteredArray as $k => $v){
echo "$k = $v";
}
You somehow have to loop through your array and filter each element by your condition. This can be done with various methods.
Loops while / for / foreach method
Loop through your array with any loop you want, may it be while, for or foreach. Then simply check for your condition and either unset() the elements if they don't meet your condition or write the elements, which meet the condition, into a new array.
Looping
//while loop
while(list($key, $value) = each($array)){
//condition
}
//for loop
$keys = array_keys($array);
for($counter = 0, $length = count($array); $counter < $length; $counter++){
$key = $keys[$counter];
$value = $array[$key];
//condition
}
//foreach loop
foreach($array as $key => $value){
//condition
}
Condition
Just place your condition into the loop where the comment //condition is. The condition can just check for whatever you want and then you can either unset() the elements which don't meet your condition, and reindex the array with array_values() if you want, or write the elements in a new array which meet the condition.
//Pseudo code
//Use one of the two ways
if(condition){ //1. Condition fulfilled
$newArray[ ] = $value;
//↑ Put '$key' there, if you want to keep the original keys
//Result array is: $newArray
} else { //2. Condition NOT fulfilled
unset($array[$key]);
//Use array_values() after the loop if you want to reindex the array
//Result array is: $array
}
array_filter() method
Another method is to use the array_filter() built-in function. It generally works pretty much the same as the method with a simple loop.
You just need to return TRUE if you want to keep the element in the array and FALSE if you want to drop the element out of the result array.
//Anonymous function
$newArray = array_filter($array, function($value, $key){
//condition
}, ARRAY_FILTER_USE_BOTH);
//Function name passed as string
function filter($value, $key){
//condition
}
$newArray = array_filter($array, "filter", ARRAY_FILTER_USE_BOTH);
//'create_function()', NOT recommended
$newArray = array_filter($array, create_function('$value, $key', '/* condition */'), ARRAY_FILTER_USE_BOTH);
preg_grep() method
preg_grep() is similar to array_filter() just that it only uses regular expression to filter the array. So you might not be able to do everything with it, since you can only use a regular expression as filter and you can only filter by values or with some more code by keys.
Also note that you can pass the flag PREG_GREP_INVERT as third parameter to invert the results.
//Filter by values
$newArray = preg_grep("/regex/", $array);
Common conditions
There are many common conditions used to filter an array of which all can be applied to the value and or key of the array. I will just list a few of them here:
//Odd values
return $value & 1;
//Even values
return !($value & 1);
//NOT null values
return !is_null($value);
//NOT 0 values
return $value !== 0;
//Contain certain value values
return strpos($value, $needle) !== FALSE; //Use 'use($needle)' to get the var into scope
//Contain certain substring at position values
return substr($value, $position, $length) === $subString;
//NOT 'empty'(link) values
array_filter($array); //Leave out the callback parameter
You can iterate on the copies of the keys to be able to use unset() in the loop:
foreach (array_keys($array) as $key) {
if ($array[$key] != 2) {
unset($array[$key]);
}
}
The advantage of this method is memory efficiency if your array contains big values - they are not duplicated.
EDIT I just noticed, that you actually only need the keys that have a value of 2 (you already know the value):
$keys = array();
foreach ($array as $key => $value) {
if ($value == 2) {
$keys[] = $key;
}
}
This should work, but I'm not sure how efficient it is as you probably end up copying a lot of data.
$newArray = array_intersect_key(
$fullarray,
array_flip(array_keys($fullarray, 2))
);
This can be handled using a closure. The following answer is inspired by PHP The Right Way:
//This will create an anonymous function that will filter the items in the array by the value supplied
function cb_equal_to($val)
{
return function($item) use ($val) {
return $item == $val;
};
}
$input = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
// Use array_filter on a input with a selected filter function
$filtered_array = array_filter($input, cb_equal_to(2));
Contents of $filtered_array would now be
array ( ["a"] => 2 ["c"] => 2 ["f"] => 2 )
I think the snappiest, readable built-in function is: array_intersect()
Code: (Demo)
$array = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
var_export(array_intersect($array, [2]));
Output:
array (
'a' => 2,
'c' => 2,
'f' => 2,
)
Just make sure you declare the 2nd parameter as an array because that is the value type expected.
Now there is nothing wrong with writing out a foreach loop, or using array_filter(), they just have a more verbose syntax.
array_intersect() is also very easy to extend (include additional "qualifying" values) by adding more values to the 2nd parameter array.
From PHP7.4, arrow function syntax is available. This affords more concise code and the ability to access global variables without use.
Code: (Demo)
$haystack = [
"a" => 2,
"b" => 4,
"c" => 2,
"d" => 5,
"e" => 6,
"f" => 2
];
$needle = 2;
var_export(
array_filter(
$haystack,
fn($v) => $v === $needle
)
);
I might do something like:
$newarray = array();
foreach ($jsonarray as $testelement){
if ($testelement == 2){$newarray[]=$testelement}
}
$result = count($newarray);
foreach ($aray as $key => $value) {
if (2 != $value) {
unset($array($key));
}
}
echo 'Items in array:' . count($array);
You can do something like:
$array = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
$arrayFiltered = array_filter($array, function ($element) {
return $element == 2;
});
or:
$arrayFiltered = array_filter($array, fn($element) => $element == 2);

How to PHP Unset Array Value [duplicate]

I have an array like this:
array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2)
Now I want to filter that array by some condition and only keep the elements where the value is equal to 2 and delete all elements where the value is NOT 2.
So my expected result array would be:
array("a" => 2, "c" => 2, "f" => 2)
Note: I want to keep the keys from the original array.
How can I do that with PHP? Any built-in functions?
$fullArray = array('a'=>2,'b'=>4,'c'=>2,'d'=>5,'e'=>6,'f'=>2);
function filterArray($value){
return ($value == 2);
}
$filteredArray = array_filter($fullArray, 'filterArray');
foreach($filteredArray as $k => $v){
echo "$k = $v";
}
You somehow have to loop through your array and filter each element by your condition. This can be done with various methods.
Loops while / for / foreach method
Loop through your array with any loop you want, may it be while, for or foreach. Then simply check for your condition and either unset() the elements if they don't meet your condition or write the elements, which meet the condition, into a new array.
Looping
//while loop
while(list($key, $value) = each($array)){
//condition
}
//for loop
$keys = array_keys($array);
for($counter = 0, $length = count($array); $counter < $length; $counter++){
$key = $keys[$counter];
$value = $array[$key];
//condition
}
//foreach loop
foreach($array as $key => $value){
//condition
}
Condition
Just place your condition into the loop where the comment //condition is. The condition can just check for whatever you want and then you can either unset() the elements which don't meet your condition, and reindex the array with array_values() if you want, or write the elements in a new array which meet the condition.
//Pseudo code
//Use one of the two ways
if(condition){ //1. Condition fulfilled
$newArray[ ] = $value;
//↑ Put '$key' there, if you want to keep the original keys
//Result array is: $newArray
} else { //2. Condition NOT fulfilled
unset($array[$key]);
//Use array_values() after the loop if you want to reindex the array
//Result array is: $array
}
array_filter() method
Another method is to use the array_filter() built-in function. It generally works pretty much the same as the method with a simple loop.
You just need to return TRUE if you want to keep the element in the array and FALSE if you want to drop the element out of the result array.
//Anonymous function
$newArray = array_filter($array, function($value, $key){
//condition
}, ARRAY_FILTER_USE_BOTH);
//Function name passed as string
function filter($value, $key){
//condition
}
$newArray = array_filter($array, "filter", ARRAY_FILTER_USE_BOTH);
//'create_function()', NOT recommended
$newArray = array_filter($array, create_function('$value, $key', '/* condition */'), ARRAY_FILTER_USE_BOTH);
preg_grep() method
preg_grep() is similar to array_filter() just that it only uses regular expression to filter the array. So you might not be able to do everything with it, since you can only use a regular expression as filter and you can only filter by values or with some more code by keys.
Also note that you can pass the flag PREG_GREP_INVERT as third parameter to invert the results.
//Filter by values
$newArray = preg_grep("/regex/", $array);
Common conditions
There are many common conditions used to filter an array of which all can be applied to the value and or key of the array. I will just list a few of them here:
//Odd values
return $value & 1;
//Even values
return !($value & 1);
//NOT null values
return !is_null($value);
//NOT 0 values
return $value !== 0;
//Contain certain value values
return strpos($value, $needle) !== FALSE; //Use 'use($needle)' to get the var into scope
//Contain certain substring at position values
return substr($value, $position, $length) === $subString;
//NOT 'empty'(link) values
array_filter($array); //Leave out the callback parameter
You can iterate on the copies of the keys to be able to use unset() in the loop:
foreach (array_keys($array) as $key) {
if ($array[$key] != 2) {
unset($array[$key]);
}
}
The advantage of this method is memory efficiency if your array contains big values - they are not duplicated.
EDIT I just noticed, that you actually only need the keys that have a value of 2 (you already know the value):
$keys = array();
foreach ($array as $key => $value) {
if ($value == 2) {
$keys[] = $key;
}
}
This should work, but I'm not sure how efficient it is as you probably end up copying a lot of data.
$newArray = array_intersect_key(
$fullarray,
array_flip(array_keys($fullarray, 2))
);
This can be handled using a closure. The following answer is inspired by PHP The Right Way:
//This will create an anonymous function that will filter the items in the array by the value supplied
function cb_equal_to($val)
{
return function($item) use ($val) {
return $item == $val;
};
}
$input = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
// Use array_filter on a input with a selected filter function
$filtered_array = array_filter($input, cb_equal_to(2));
Contents of $filtered_array would now be
array ( ["a"] => 2 ["c"] => 2 ["f"] => 2 )
I think the snappiest, readable built-in function is: array_intersect()
Code: (Demo)
$array = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
var_export(array_intersect($array, [2]));
Output:
array (
'a' => 2,
'c' => 2,
'f' => 2,
)
Just make sure you declare the 2nd parameter as an array because that is the value type expected.
Now there is nothing wrong with writing out a foreach loop, or using array_filter(), they just have a more verbose syntax.
array_intersect() is also very easy to extend (include additional "qualifying" values) by adding more values to the 2nd parameter array.
From PHP7.4, arrow function syntax is available. This affords more concise code and the ability to access global variables without use.
Code: (Demo)
$haystack = [
"a" => 2,
"b" => 4,
"c" => 2,
"d" => 5,
"e" => 6,
"f" => 2
];
$needle = 2;
var_export(
array_filter(
$haystack,
fn($v) => $v === $needle
)
);
I might do something like:
$newarray = array();
foreach ($jsonarray as $testelement){
if ($testelement == 2){$newarray[]=$testelement}
}
$result = count($newarray);
foreach ($aray as $key => $value) {
if (2 != $value) {
unset($array($key));
}
}
echo 'Items in array:' . count($array);
You can do something like:
$array = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
$arrayFiltered = array_filter($array, function ($element) {
return $element == 2;
});
or:
$arrayFiltered = array_filter($array, fn($element) => $element == 2);

Shuffle the order of keys in an associative array, if they have the same values?

Given an associative array like this, how can you shuffle the order of keys that have the same value?
array(a => 1,
b => 2, // make b or c ordered first, randomly
c => 2,
d => 4,
e => 5, // make e or f ordered first, randomly
f => 5);
The approach I tried was to turn it into a structure like this and shuffle the values (which are arrays of the original keys) and then flatten it back into the original form. Is there a simpler or cleaner approach? (I'm not worried about efficiency, this is for small data sets.)
array(1 => [a],
2 => [b, c], // shuffle these
4 => [d],
5 => [e, f]); // shuffle these
function array_sort_randomize_equal_values($array) {
$collect_by_value = array();
foreach ($array as $key => $value) {
if (! array_key_exists($value, $collect_by_value)) {
$collect_by_value[$value] = array();
}
// note the &, we want to modify the array, not get a copy
$subarray = &$collect_by_value[$value];
array_push($subarray, $key);
}
arsort($collect_by_value);
$reordered = array();
foreach ($collect_by_value as $value => $array_of_keys) {
// after randomizing keys with the same value, create a new array
shuffle($array_of_keys);
foreach ($array_of_keys as $key) {
array_push($reordered, $value);
}
}
return $reordered;
}
I rewrote the entire code, since I found another way which is a lot simpler and faster than the old one(If you are still interested in the old one see the revision):
old code (100,000 executions): Ø 4.4 sec.
new code (100,000 executions): Ø 1.3 sec.
Explanation
First we get all unique values from the array with array_flip(), since then the values are the keys and you can't have duplicate keys in an array we have our unique values. We also create an array $result for then storing our result in it and $keyPool for storing all keys for each value.
Now we loop through our unique values and get all keys which have the same value into an array with array_keys() and save it in $keyPool with the value as key. We can also right away shuffle() the keys array, so that they are already random:
foreach($uniqueValues as $value => $notNeeded){
$keyPool[$value] = array_keys($arr, $value, TRUE);
shuffle($keyPool[$value]);
}
Now we can already loop through our original array and get a key with array_shift() from the $keyPool for each value and save it in $result:
foreach($arr as $value)
$result[array_shift($keyPool[$value])] = $value;
Since we already shuffled the array the keys already have a random order and we just use array_shift(), so that we can't use the key twice.
Code
<?php
$arr = ["a" => 1, "b" => 1, "c" => 1, "d" => 1, "e" => 1, "f" => 2,
"g" => 1, "h" => 3, "i" => 4, "j" => 5, "k" => 5];
function randomize_duplicate_array_value_keys(array $arr){
$uniqueValues = array_flip($arr);
$result = [];
$keyPool = [];
foreach($uniqueValues as $value => $notNeeded){
$keyPool[$value] = array_keys($arr, $value, TRUE);
shuffle($keyPool[$value]);
}
foreach($arr as $value)
$result[array_shift($keyPool[$value])] = $value;
return $result;
}
$result = randomize_duplicate_array_value_keys($arr);
print_r($result);
?>
(possible) output:
Array (
[b] => 1
[g] => 1
[a] => 1
[e] => 1
[d] => 1
[f] => 2
[c] => 1
[h] => 3
[i] => 4
[k] => 5
[j] => 5
)
Footnotes
I used array_flip() instead of array_unique() to get the unique values from the array, since it's slightly faster.
I also removed the if statement to check if the array has more than one elements and needs to be shuffled, since with and without the if statement the code runs pretty much with the same execution time. I just removed it to make it easier to understand and the code more readable:
if(count($keyPool[$value]) > 1)
shuffle($keyPool[$value]);
You can also make some optimization changes if you want:
Preemptively return, if you get an empty array, e.g.
function randomize_duplicate_array_value_keys(array $arr){
if(empty($arr))
return [];
$uniqueValues = array_flip($arr);
$result = [];
//***
}
Preemptively return the array, if it doesn't have duplicate values:
function randomize_duplicate_array_value_keys(array $arr){
if(empty($arr))
return [];
elseif(empty(array_filter(array_count_values($arr), function($v){return $v > 1;})))
return [];
$uniqueValues = array_flip($arr);
$result = [];
//***
}
Here's another way that iterates through the sorted array while keeping track of the previous value. If the previous value is different than the current one, then the previous value is added to a new array while the current value becomes the previous value. If the current value is the same as the previous value, then depending on the outcome of rand(0,1) either the previous value is added to the new list as before, or the current value is added to the new list first:
<?php
$l = ['a' => 1,'b' => 2, 'c' => 2,
'd' => 4,'e' => 5,'f' => 5];
asort($l);
$prevK = key($l);
$prevV = array_shift($l); //initialize prev to 1st element
$shuffled = [];
foreach($l as $k => $v) {
if($v != $prevV || rand(0,1)) {
$shuffled[$prevK] = $prevV;
$prevK = $k;
$prevV = $v;
}
else {
$shuffled[$k] = $v;
}
}
$shuffled[$prevK] = $prevV;
print_r($shuffled);

How to filter an array by a condition

I have an array like this:
array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2)
Now I want to filter that array by some condition and only keep the elements where the value is equal to 2 and delete all elements where the value is NOT 2.
So my expected result array would be:
array("a" => 2, "c" => 2, "f" => 2)
Note: I want to keep the keys from the original array.
How can I do that with PHP? Any built-in functions?
$fullArray = array('a'=>2,'b'=>4,'c'=>2,'d'=>5,'e'=>6,'f'=>2);
function filterArray($value){
return ($value == 2);
}
$filteredArray = array_filter($fullArray, 'filterArray');
foreach($filteredArray as $k => $v){
echo "$k = $v";
}
You somehow have to loop through your array and filter each element by your condition. This can be done with various methods.
Loops while / for / foreach method
Loop through your array with any loop you want, may it be while, for or foreach. Then simply check for your condition and either unset() the elements if they don't meet your condition or write the elements, which meet the condition, into a new array.
Looping
//while loop
while(list($key, $value) = each($array)){
//condition
}
//for loop
$keys = array_keys($array);
for($counter = 0, $length = count($array); $counter < $length; $counter++){
$key = $keys[$counter];
$value = $array[$key];
//condition
}
//foreach loop
foreach($array as $key => $value){
//condition
}
Condition
Just place your condition into the loop where the comment //condition is. The condition can just check for whatever you want and then you can either unset() the elements which don't meet your condition, and reindex the array with array_values() if you want, or write the elements in a new array which meet the condition.
//Pseudo code
//Use one of the two ways
if(condition){ //1. Condition fulfilled
$newArray[ ] = $value;
//↑ Put '$key' there, if you want to keep the original keys
//Result array is: $newArray
} else { //2. Condition NOT fulfilled
unset($array[$key]);
//Use array_values() after the loop if you want to reindex the array
//Result array is: $array
}
array_filter() method
Another method is to use the array_filter() built-in function. It generally works pretty much the same as the method with a simple loop.
You just need to return TRUE if you want to keep the element in the array and FALSE if you want to drop the element out of the result array.
//Anonymous function
$newArray = array_filter($array, function($value, $key){
//condition
}, ARRAY_FILTER_USE_BOTH);
//Function name passed as string
function filter($value, $key){
//condition
}
$newArray = array_filter($array, "filter", ARRAY_FILTER_USE_BOTH);
//'create_function()', NOT recommended
$newArray = array_filter($array, create_function('$value, $key', '/* condition */'), ARRAY_FILTER_USE_BOTH);
preg_grep() method
preg_grep() is similar to array_filter() just that it only uses regular expression to filter the array. So you might not be able to do everything with it, since you can only use a regular expression as filter and you can only filter by values or with some more code by keys.
Also note that you can pass the flag PREG_GREP_INVERT as third parameter to invert the results.
//Filter by values
$newArray = preg_grep("/regex/", $array);
Common conditions
There are many common conditions used to filter an array of which all can be applied to the value and or key of the array. I will just list a few of them here:
//Odd values
return $value & 1;
//Even values
return !($value & 1);
//NOT null values
return !is_null($value);
//NOT 0 values
return $value !== 0;
//Contain certain value values
return strpos($value, $needle) !== FALSE; //Use 'use($needle)' to get the var into scope
//Contain certain substring at position values
return substr($value, $position, $length) === $subString;
//NOT 'empty'(link) values
array_filter($array); //Leave out the callback parameter
You can iterate on the copies of the keys to be able to use unset() in the loop:
foreach (array_keys($array) as $key) {
if ($array[$key] != 2) {
unset($array[$key]);
}
}
The advantage of this method is memory efficiency if your array contains big values - they are not duplicated.
EDIT I just noticed, that you actually only need the keys that have a value of 2 (you already know the value):
$keys = array();
foreach ($array as $key => $value) {
if ($value == 2) {
$keys[] = $key;
}
}
This should work, but I'm not sure how efficient it is as you probably end up copying a lot of data.
$newArray = array_intersect_key(
$fullarray,
array_flip(array_keys($fullarray, 2))
);
This can be handled using a closure. The following answer is inspired by PHP The Right Way:
//This will create an anonymous function that will filter the items in the array by the value supplied
function cb_equal_to($val)
{
return function($item) use ($val) {
return $item == $val;
};
}
$input = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
// Use array_filter on a input with a selected filter function
$filtered_array = array_filter($input, cb_equal_to(2));
Contents of $filtered_array would now be
array ( ["a"] => 2 ["c"] => 2 ["f"] => 2 )
I think the snappiest, readable built-in function is: array_intersect()
Code: (Demo)
$array = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
var_export(array_intersect($array, [2]));
Output:
array (
'a' => 2,
'c' => 2,
'f' => 2,
)
Just make sure you declare the 2nd parameter as an array because that is the value type expected.
Now there is nothing wrong with writing out a foreach loop, or using array_filter(), they just have a more verbose syntax.
array_intersect() is also very easy to extend (include additional "qualifying" values) by adding more values to the 2nd parameter array.
From PHP7.4, arrow function syntax is available. This affords more concise code and the ability to access global variables without use.
Code: (Demo)
$haystack = [
"a" => 2,
"b" => 4,
"c" => 2,
"d" => 5,
"e" => 6,
"f" => 2
];
$needle = 2;
var_export(
array_filter(
$haystack,
fn($v) => $v === $needle
)
);
I might do something like:
$newarray = array();
foreach ($jsonarray as $testelement){
if ($testelement == 2){$newarray[]=$testelement}
}
$result = count($newarray);
foreach ($aray as $key => $value) {
if (2 != $value) {
unset($array($key));
}
}
echo 'Items in array:' . count($array);
You can do something like:
$array = array("a" => 2, "b" => 4, "c" => 2, "d" => 5, "e" => 6, "f" => 2);
$arrayFiltered = array_filter($array, function ($element) {
return $element == 2;
});
or:
$arrayFiltered = array_filter($array, fn($element) => $element == 2);

Categories