Converting Boolean values inside array into if statement - php

What is the best way to convert array values in to if statement. The array values should be compared by AND and the arrays by OR. I can do this using EVAL but looking for something other than EVAL.
$arr = Array(
[0] => Array
(
[0] => false
[1] => true
)
[1] => Array
(
[0] => true
[1] => false
)
[2] => Array
(
[0] => false
)
[3] => Array
(
[0] => true
)
[4] => Array
(
[0] => true,
[1] => true,
[2] => true
)
)
I want to build comparison dynamically for if statement..
For example
if( ($arr[0][0] && $arr[0][1]) || ($arr[1][0] && $arr[1][1]) .... and so on )

$result = array_reduce($arr, function ($result, array $values) {
return $result || array_reduce($values, function ($result, $value) {
return $result && $value;
}, true);
}, false);
if ($result) ...
One array_reduce can elegantly do this for one array, you simply want to do it for two nested array levels.

What you are doing is generating a single boolean from values in an array. This is known as reduce operation. In php, we can do this with array_reduce(..).
array_reduce($input,
function($prev, $item) {
//Short-circuit if we already deduced it to be true
if($prev) {
return $prev;
}
//If one value is false, the entire thing is false
foreach($item as $k => $v) {
if(!$v) {
return false;
}
}
//All were true
return true;
}, false);

Related

array_column doesn't work with first key in nested array

I have a nested array like so
$array = array(
[2] => array(
[5] => array(
[7] => array(
[46] => array()
)
),
[108] => array()
),
[14] => array(),
[8] => array(
[72] => array()
)
)
With only knowing the key, I need to find it in the array and get all it's nested data. Using array_column only works if I start with a second level key
$foo = array_column($array, 2) // returns empty array
$bar = array_column($array, 5) // returns all its nested data
Why is that and what's the correct way to do this with any key without knowing the level
This is a recursive function which at each point checks if the key matches the required one, if so it returns the value, if not it will look in elements which are also arrays (which is where the recursive bit comes in) and return if a match is found there...
function nested_array_key_search ( array $array, $key ) {
foreach ( $array as $elementKey => $element ) {
if ( $elementKey === $key ) {
return $element;
}
if ( is_array($element) ) {
$nested = nested_array_column ( $element, $key );
// If the recursive call returns a value
if ( $nested !== false ) {
return $nested;
}
}
}
// Not found, return false
return false;
}
$bar = nested_array_key_search($array, 2);
print_r($bar);
gives...
Array
(
[5] => Array
(
[7] => Array
(
[46] => Array
(
)
)
)
[108] => Array
(
)
)

PHP - Get value from keys in multidimensional array

Here is my array
$myArray = Array(
[63145] => Array
(
[id] => 63145
[name] => banana
[type] => fruit
)
[244340] => Array
(
[id] => 244340
[name] => apple
[type] => fruit
)
[253925] => Array
(
[id] => 253925
[name] => portato
[type] => vegetable
)
[233094] => Array
(
[id] => 233094
[name] => carrot
[type] => vegetable
));
How do i loop through this and pull out the ids of all fruits, so i kan use them in another foreach loop?
maybe with a If statement, so that if(type == fruit) use the ids in the foreach loop.
I have tried to look through other questions but I can't figure out how to convert the answers to my array (I know I'm a noob)..
The naïve:
$fruitIds = [];
foreach ($myArray as $item) {
if ($item['type'] == 'fruit') {
$fruitIds[] = $item['id'];
}
}
The functional:
$fruitIds = array_column(
array_filter($myArray, function (array $i) { return $i['type'] == 'fruit'; }),
'id'
);
The more efficient functional:
$fruitIds = array_reduce($myArray, function (array $ids, array $i) {
return array_merge($ids, $i['type'] == 'fruit' ? [$i['id']] : []);
}, []);
You can do this using PHP's array_column and array_filter:
$fruit_ids = array_column(array_filter($arr, function($item, $index) {
return $item['type'] == 'fruit';
}), 'id');
But also your array keys seem to be the same as your id values on the child arrays, so you could mix array_filter with array_keys:
$fruit_ids = array_keys(array_filter($arr, function($item, $index) {
return $item['type'] == 'fruit';
}));

How to filter a two dimensional array by value

How would I create a function that filters a two dimensional array by value?
Given the following array :
Array
(
[0] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => CarEnquiry
[status] => NEW
[appointment] => 0
)
[1] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => CarEnquiry
[status] => CALL1
[appointment] => 0
)
[2] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => Finance
[status] => CALL2
[appointment] => 0
)
[3] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => Partex
[status] => CALL3
[appointment] => 0
)
How would I filter the array to only show those arrays that contain a specific value in the name key? For example name = 'CarEnquiry'.
The resulting output would be:
Array
(
[0] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => CarEnquiry
[status] => NEW
[appointment] => 0
)
[1] => Array
(
[interval] => 2014-10-26
[leads] => 0
[name] => CarEnquiry
[status] => CALL1
[appointment] => 0
)
)
EDIT
I forgot to mention that the search value should be interchangeable - i.e. name = 'CarEnquiry' or name = 'Finance'.
Use PHP's array_filter function with a callback.
$new = array_filter($arr, function ($var) {
return ($var['name'] == 'CarEnquiry');
});
Edit: If it needs to be interchangeable, you can modify the code slightly:
$filterBy = 'CarEnquiry'; // or Finance etc.
$new = array_filter($arr, function ($var) use ($filterBy) {
return ($var['name'] == $filterBy);
});
If you want to make this a generic function use this:
function filterArrayByKeyValue($array, $key, $keyValue)
{
return array_filter($array, function($value) use ($key, $keyValue) {
return $value[$key] == $keyValue;
});
}
<?php
function filter_array($array,$term){
$matches = array();
foreach($array as $a){
if($a['name'] == $term)
$matches[]=$a;
}
return $matches;
}
$new_array = filter_array($your_array,'CarEnquiry');
?>
Above examples are using the exact word match, here is a simple example for filtering array to find imprecise "name" match.
$options = array_filter($options, function ($option) use ($name) {
return strpos(strtolower($option['text']), strtolower($name)) !== FALSE;
});
array_filter is the function you need. http://php.net/manual/en/function.array-filter.php
Give it a filtering function like this:
function my_filter($elt) {
return $elt['name'] == 'something';
}
function multi_array_search_with_condition($array, $condition)
{
$foundItems = array();
foreach($array as $item)
{
$find = TRUE;
foreach($condition as $key => $value)
{
if(isset($item[$key]) && $item[$key] == $value)
{
$find = TRUE;
} else {
$find = FALSE;
}
}
if($find)
{
array_push($foundItems, $item);
}
}
return $foundItems;
}
This my function can use about this problem. You can use:
$filtered = multi_array_search_with_condition(
$array,
array('name' => 'CarEnquiry')
);
This will get your filtered items from your 2 dimensional array.

Group related elements in array

I have an array in the following format:
[8106] => Array (
[id1] => 210470
[id2] => 216298
)
[8107] => Array (
[id1] => 210470
[id2] => 187145
)
[8108] => Array (
[id1] => 187145
[id2] => 216298
)
[8109] => Array (
[id1] => 187145
[id2] => 210470
)
[8110] => Array (
[id1] => 266533
[id2] => 249612
)
[8111] => Array (
[id1] => 249612
[id2] => 266533
)
I need to get it into the following format:
[0] => Array (
[0] => 266533
[1] => 249612
)
[1] => Array (
[0] => 187145
[1] => 210470
[2] => 216298
)
Basically, I need to extract all the ids, keep the relationships, but group them all together. I have a function to do this, but it takes forever (I am up to 30+ minutes on the number of rows I have to run through). Keys and order are unimportant. The relationship is all that is important. I am looking for a faster method. The function(s) I am using are below:
function getMatchingIDs($filteredArray)
{
$result = array();
$resultCount = 0;
foreach ($filteredArray as $details) {
$imaId1 = inMultiArray($details['id1'], $result);
$imaId2 = inMultiArray($details['id2'], $result);
if ($imaId1 === false && $imaId2 === false) {
$result[$resultCount++] = array(
$details['id1'],
$details['id2'],
);
} elseif (is_numeric($imaId1) === true && $imaId2 === false) {
$result[$imaId1][] = $details['id2'];
} elseif ($imaId1 === false && is_numeric($imaId2) === true) {
$result[$imaId2][] = $details['id1'];
} elseif ($imaId2 != $imaId1) {
$result[$imaId1] = array_merge($result[$imaId1], $result[$imaId2]);
unset($result[$imaId2]);
}
}
return $result;
}
function inMultiArray($elem, $array)
{
if (is_array($array) === true) {
// if the variable $elem is in the variable $array return true
if (is_array($array) === true && in_array($elem, $array) === true) {
return true;
}
// if $elem isn't in $array, then check foreach element
foreach ($array as $key => $arrayElement) {
// if $arrayElement is an array call the inMultiArray function to this element
// if inMultiArray returns true, than return is in array, else check next element
if (is_array($arrayElement) === true) {
$value = inMultiArray($elem, $arrayElement);
if ($value === true) {
return $key;
}
}
}
}
// if isn't in array return false
return false;
}
$filtered = getMatchingIDs($unfiltered);
EDIT: The original array describes relations between pairs of ids (not shown in the array). The desired output is that the relations are further defined. If you look in the original array, elements 8106-8109 are simply paired combinations of three ids. I need those three grouped together. Elements 8110 and 8111 are a distinct pair, just in a different order.
$newArray = array();
foreach ($array as $k => $v) {
$newArray[0][] = $v['id1'];
$newArray[1][] = $v['id2'];
}
What I finally ended up doing was in essence creating an index array. This array held all the positions of each value in the primary array.
So the following array
[0] => Array (
[0] => 266533
[1] => 249612
)
[1] => Array (
[0] => 187145
[1] => 210470
[2] => 216298
)
has an index of:
[187145] => 1
[210470] => 1
[216298] => 1
[249612] => 0
[266533] => 0
So instead of looking for the value in the primary multidimensional array, I check to see if it exists in the index array and process the data based on that. The results are that it now runs the entire process in <5 seconds instead of > 1 hour.
Thank you for your help.

PHP function returning array index path

I've been trying to write a PHP function which searches the id index valeus in array, and once found, returns the path which lead to it's discovery.
Take the following array:
Array
(
[0] => Array
(
[id] => 1
[data] => Array
(
[0] => Array
(
[id] => 8
)
[1] => Array
(
[id] => 9
)
[2] => Array
(
[id] => 10
[data] => Array
(
[0] => Array
(
[id] => 15
[data] => Array
(
[0] => Array
(
[id] => 22
)
)
)
[1] => Array
(
[id] => 21
)
)
)
)
)
)
If looking for [id] => 21 it would return array(1,10). However, in numerous attempts I have failed. The set path should be set to the index id. However, I cannot figure it out. Any words of guidance are much appreciated.
This functions returns array(1,10) for OP example
(will leave that other answer just in case someone will look for normal "path searching")
function search_data($needle, $haystack) {
if (is_array($haystack)) {
foreach($haystack as $data) {
if ($data['id'] == $needle) return array();
if (isset($data['data'])) {
if (($path = search_data($needle, $data['data'])) !== false) return array_merge(array($data['id']), $path);
}
}
}
return false;
}
This functions returns array(0,'data',2,'data',1,'id') for OP example (i.e. full path to value)
Function which searches for $key => $value pair in array and returns the path:
function array_search_r($key, $value, $haystack, $strict = null) {
$strict = $strict ?: false;
if (is_array($haystack)) {
foreach($haystack as $k => $v) {
if ($strict ? ($k === $key && $v === $value) : ($k == $key && $v == $value)) return array($k);
if(($path = array_search_r($key, $value, $v, $strict)) !== false) return array_merge(array($k), $path);
}
}
return false;
}

Categories