Related
I'm looking for the way to combine 2 foraech loops into one (merge 2 functions):
The result function should return both: ($is - boolean & $d - array).
Traversable data in both functions - the same.
Is it possible? What will be a good solution for that?
public function func1($p, $c) {
$is = 0;
if (!empty($p)) {
foreach($p as $k=>$v) {
if ((!empty($c['prod']) && $c['prod'] == $v['ref'] && $c['status'])) {
$is = 1;
break;
}
}
}
return $is;
}
public function func2($p) {
$d = [];
if (!empty($p)) {
foreach($p as $k=>$v) {
$prod = [
'name' => $v['name'],
'price' => $v['price'],
'reference' => $v['ref']
];
$d[] = $prod;
}
}
return $d;
}
Thanks.
My take, but not tested.
public function func3($p, $c) {
$is = 0;
$d = [];
if (!empty($p)) {
foreach($p as $k=>$v) {
$d[] = [
'name' => $v['name'],
'price' => $v['price'],
'reference' => $v['ref']
];
if ($is === 0 && (!empty($c['prod']) && $c['prod'] == $v['ref'] && $c['status'])) {
$is = 1;
}
}
}
return [$is, $d];
}
I have an array lets suppose
$myarr = array(
'1',
'2',
'3',
'4-7',
'9',
'10',
)
$search2 = '2';
$search5 = '5';
I want to check both these 2 variables inside my $myarr. The first one can be easily found by using in_array but the $search5 is there inside '4-7' but what will I do to find the value? I don't want 2 foreach because i know I can use explode and then compare the start and end value. Is there a single or double line function that could help me achieve what I need? Thanks
PHP code demo
<?php
ini_set("display_errors", 1);
$search=2;
$result=null;
$myarr = array(
'1',
'2',
'3',
'4-7',
'9',
'10',
);
echo search_in_array($myarr,$search);
function search_in_array($myarr,$search)
{
$result=false;
array_map(function($number) use ($myarr,$search, &$result){
if(preg_match("/^(\d+)\-(\d+)$/", $number,$matches))
{
if(in_array($search,range($matches[1],$matches[2])))
{
$result= true;
}
}
elseif(preg_match("/^(\d+)$/", $number,$matches))
{
if(in_array($search,$myarr))
{
$result= true;
}
}
}, $myarr);
return $result;
}
Just as another answer:
$myarr = [
'1',
'2',
'3',
'4-7',
'9',
'10',
];
$search2 = '2';
$search5 = '5';
$search12 = '12';
function myInArray($needle, $haystack) {
return in_array(
$needle,
array_reduce(
$haystack,
function($incrementor, $value) {
return array_merge($incrementor, (strpos($value, '-') !== false) ? range(...explode('-', $value)) : [(int)$value]);
},
[]
)
);
}
foreach([$search2, $search5, $search12] as $searchValue) {
echo $searchValue, " is ",(myInArray($searchValue, $myarr) ? '' : 'NOT '), "in the array", PHP_EOL;
}
Probably not as efficient, especially when working with larger ranges of values in $myarr, but a slightly different approach
Demo
Here is almost one-liner,
$search = '5';
$matches = explode('-',array_values(preg_grep('/[-]/', $myarr))[0]);
if(in_array($search, $myarr)|| in_array($search,range($matches[0],$matches[1]))){
echo "found";
}else{
echo "not found";
}
I am exploding by - and then creating range with that and checking that with in_array.
Here is working DEMO
<?php
$myarr = ['1', '2', '3', '4-7', '9', '10'];
$search_array = [2, 5];
$search_results = [];
for ($i = 0; $i < count($search_array); $i++) {
$search_results[$search_array[$i]] = array_search($search_array[$i], $myarr);
if (!$search_results[$search_array[$i]]) {
foreach ($myarr as $value) {
if (strpos($value, "-") !== false) {
$data = explode("-", $value);
if ($search_array[$i] >= $data[0] && $search_array[$i] <= $data[1]) {
$search_results[$search_array[$i]] = array_search($value, $myarr);
}
}
}
}
if (!$search_results[$search_array[$i]]) {
unset($search_results[$search_array[$i]]);
}
}
var_dump($search_results);
Obviously using single foreach i cam up with this code to find ... set of data another is for loop not foreach.
#Ali Zia you can also try this logic like below:
<?php
$myarr = array(
'1',
'2',
'3',
'4-7',
'9',
'10',
);
$flag = 0;
$search = '5';
foreach($myarr as $value){
if($value == $search){
$flag = 1;
break;
}
else if(strpos($value, "-")){
$numberRange = explode("-", $value);
if($numberRange[0] <= $search && $numberRange[1] >= $search){
$flag = 1;
break;
}
}
}
if($flag == 1){
echo "yes number found in the array";
}
else{
echo "sorry not found";
}
Just for the sake of using range() and argument unpacking, because none of the other answers do:
function in_array_range($needle, array $haystack) {
if (in_array((int) $needle, $haystack, true)) {
return true;
}
$haystack = array_map(
function($element) {
return strpos($element, '-')
? range(... explode('-', $element, 2))
: (int) $element;
},
$haystack
);
foreach ($haystack as $element) {
if (is_array($element) && in_array((int) $needle, $element, true)) {
return true;
}
}
return false;
}
The function below returns the index of $needle in $haystack or -1 if no such element has been found.
function find(array $haystack, $needle) {
for ($i = 0; $i < count($haystack); $i++) {
$parts = explode("-", $haystack[$i]);
if (count($parts) == 2) {
if ($needle >= $parts[0] && $needle <= $parts[1]) {
return $i;
}
}
else if ($needle == $parts[0]) {
return $i;
}
}
return -1;
}
The function assumes that $array only contains a single non-negative integer or two non-negative integers separated by a dash.
You can now collect the indices like this:
$indices = array();
foreach ($searchValues as $searchValue) {
$indices[] = find($myarr, $searchValue);
}
Try with following code :
$myarr = array('1','2','3','4-7','9','10');
$search = 1; // Try with 5
$flag1 = false;
foreach($myarr as $number){
if(!is_numeric($number)){
list($start,$end) = explode("-",$number);
if($search >=$start && $search <=$end ){
echo $search .' Found';
}
}else if($flag1 == false){
if(in_array($search,$myarr)){
echo $search .' Found';
$flag1 = true;
}
}
}
Working Demo
I know the answer has already been accepted but here is my approach w/ and w/o using foreach.
(See demo).
With foreach :
<?php
$value = 3;
foreach($myarr as $myval){
list($start, $end) = strpos($myval, '-') ? explode('-', $myval) : [$myval, $myval];
if($value >= $start && $value <= $end){
echo $value . ' found between "' . $start . '" & "' . $end . '" !' . "\n";
}
}
Without foreach, "one line" code :
<?php
$value = 5;
$trueValues = [1,5];
$falseValues = [5, 7, 8];
var_dump(!count(array_diff($trueValues,array_reduce($myarr,function($arr, $item){return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);},[]))));
var_dump(!count(array_diff($falseValues,array_reduce($myarr,function($arr, $item){return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);},[]))));
var_dump(in_array($value, array_reduce($myarr, function($arr, $item){return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);}, array())));
Unfolded :
<?php
var_dump(
!count(
array_diff(
$trueValues,
array_reduce(
$myarr,
function($arr, $item){
return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);
},
[]
)
)
)
);
EDIT : Didn't know the ellipsis operator, thank you #Mark Baker
I have an array with the following keys:
Array
{
[vegetable_image] =>
[vegetable_name] =>
[vegetable_description] =>
[fruit_image] =>
[fruit_name] =>
[fruit_description] =>
}
and I would like to split them based on the prefix (vegetable_ and fruit_), is this possible?
Currently, I'm trying out array_chunk() but how do you store them into 2 separate arrays?
[vegetables] => Array { [vegetable_image] ... }
[fruits] => Array { [fruit_image] ... }
This should work for you:
$fruits = array();
$vegetables = array();
foreach($array as $k => $v) {
if(strpos($k,'fruit_') !== false)
$fruits[$k] = $v;
elseif(strpos($k,'vegetable_') !== false)
$vegetables[$k] = $v;
}
As an example see: http://ideone.com/uNi54B
Out of the Box
function splittArray($base_array, $to_split, $delimiter='_') {
$out = array();
foreach($to_split as $key) {
$search = $key.delimiter;
foreach($base_array as $ok=>$val) {
if(strpos($ok,$search)!==false) {
$out[$key][$ok] = $val;
}
}
return $out;
}
$new_array = splittArray($array,array('fruit','vegetable'));
It is possible with array_reduce()
$array = ['foo_bar' => 1, 'foo_baz' => 2, 'bar_fee' => 6, 'bar_feo' => 9, 'baz_bee' => 7];
$delimiter = '_';
$result = array_reduce(array_keys($array), function ($current, $key) use ($delimiter) {
$splitKey = explode($delimiter, $key);
$current[$splitKey[0]][] = $key;
return $current;
}, []);
Check the fiddle
Only one thins remains: you are using different forms (like "vegetable_*" -> "vegetables"). PHP is not smart enough to substitute language (that would be English language in this case) transformations like that. But if you like, you may create array of valid forms for that.
Use explode()
$arrVeg = array();
$arrFruit = array();
$finalArr = array();
foreach($array as $k => $v){
$explK = explode('_',$k);
if($explK[0] == 'vegetable'){
$arrVeg[$k] = $v;
} elseif($explK[0] == 'fruit') {
$arrFruit[$k] = $v;
}
}
$finalArr['vegetables'] = $arrVeg;
$finalArr['fruits'] = $arrFruit;
Use simple PHP array traversing and substr() function.
<?php
$arr = array();
$arr['vegetable_image'] = 'vegetable_image';
$arr['vegetable_name'] = 'vegetable_name';
$arr['vegetable_description'] = 'vegetable_description';
$arr['fruit_image'] = 'fruit_image';
$arr['fruit_name'] = 'fruit_name';
$arr['fruit_description'] = 'fruit_description';
$fruits = array();
$vegetables = array();
foreach ($arr as $k => $v) {
if (substr($k, 0, 10) == 'vegetable_') {
$vagetables[$k] = $v;
}
else if (substr($k, 0, 6) == 'fruit_') {
$fruits[$k] = $v;
}
}
print_r($fruits);
print_r($vagetables);
Working Example
is there a simple way to access the nth element in a multidimensional array in php?
so for example
$arr = array(
[0] => array(1,4,7,3,53),
[6] => array(6,3,9,12,51,7),
[2] => array(9,94,54,3,87));
the 12th element would be 9.
array keys are not necessarily in order, nor each array row is of the same length.
Try this :
<?php
$arr = array(
'0'=> array(1,4,7,3,53),
'6'=>array(6,3,9,12,51,7),
'2'=>array(9,94,54,3,87)
);
$newArray=array();
foreach($arr as $array){
$newArray=array_merge($newArray, $array);
}
echo $newArray[11];
?>
untested, should work...
$arr = array(
0 => array(1,4,7,3,53), // your code was wrong here
6 => array(6,3,9,12,51,7),
2 => array(9,94,54,3,87));
function getnth ($array, $offset) {
$tmp_arr = array();
foreach ($array as $key => $value) {
foreach ($value as $val) {
$tmp_arr[] = $val;
}
}
return (isset($tmp_arr[$offset -1]) ? $tmp_arr[$offset -1] : FALSE);
}
getnth($arr, 12);
Edit: got to admit, the array_merge version is better....
Edit2: this is probably faster, if performance is an issue....
function getnth($array, $offset) {
$i = 0;
foreach ($array as $key => $value){
$size = count($value);
$i += $size;
if($offset <= $i) {
$new_off = $size - ($i - $offset) -1 ;
return $value[$new_off];
}
}
return FALSE;
}
function get_item($arr, $path, $delim = '.') {
$path = explode($delim, $path);
$result = $arr;
foreach ($path as $item) {
if (isset($result[$item])) {
$result = $result[$item];
} else {
return null;
}
}
return $result;
}
using:
echo get_item($arr, 'item.value.3.4.2.etc');
I need to get all the combinations and permutations of an array of array of values. See snippet for example:
$a = array(
1,
2
);
$b = array(
'foo',
'bar'
);
$params = array();
$params[] = $a;
$params[] = $b;
// What to do to $params so I can get the following combinations/permutations?
// 1,foo
// 2,foo
// 1,bar
// 2,bar
// foo,1
// bar,1
// foo,2
// bar,2
Keep in mind that the $params can be any size and the items in it can also be any size.
function all($array, $partial, &$result) {
if ($array == array()) {
$result[] = implode(',', $partial);
return;
}
for($i=0; $i<count($array);$i++) {
$e = $array[$i];
$a = $array;
array_splice($a, $i, 1);
foreach($e as $v) {
$p = $partial;
$p[] = $v;
all($a, $p, $result);
}
}
}
Test:
$a = array(1, 2, 3);
$b = array('foo', 'bar');
$c = array('a', 'b');
$params = array($a, $b, $c);
$result = array();
all($params, array(), $result);
print_r($result);
Note: if there is a chance for duplicates (arrays contain the same values) you can check for duplicates before inserting into the $result.
Here is my solution. It should work with any number of associative arrays, even if they contained nested associative arrays.
<?php
$a = array(1,2,3);
$b = array('foo','bar','baz', array('other','other2',array('other3','other4')));
$params = array();
$params[] = $a;
$params[] = $b;
$elements = array();
foreach($params as $param) {
addElement($param,$elements);
}
function addElement($arg,&$result) {
if(!is_array($arg)) {
$result[] = $arg;
} else {
foreach($arg as $argArray) {
addElement($argArray,$result);
}
}
}
for($i=0; $i<count($elements); $i++) {
$curElement = $elements[$i];
for($j=0; $j<count($elements); $j++) {
if($elements[$j] != $curElement) {
$final_results[] = $curElement.','.$elements[$j];
}
}
}
print_r($final_results);
?>
http://codepad.viper-7.com/XEAKFM
Here's a possible solution codepad...
$array = array(
0 => array(
'foo',
'bar'
),
1 => array(
1,
2,
3
),
2 => array(
'x',
'y',
'z'
),
3 => array(
7,
8,
9
)
);
array_permutations($array, $permutations);
print_r($permutations);
public function array_permutations($array, &$permutations, $current_key = 0, $current_subkey = 0)
{
if(!isset($array[$current_key][$current_subkey]))
{
return;
}
$current_val = $array[$current_key][$current_subkey];
foreach($array as $array_key => $row)
{
foreach($row as $row_key => $sub_val)
{
if($array_key === $current_key)
{
if($row_key !== $current_subkey)
{
$permutations[] = $current_val . ', ' . $sub_val;
}
}
else
{
$permutations[] = $current_val . ', ' . $sub_val;
}
}
}
$next_key = ($current_subkey == (count($array[$current_key]) - 1)) ? $current_key + 1 : $current_key;
$next_subkey = ($next_key > $current_key) ? 0 : $current_subkey + 1;
array_permutations($array, $permutations, $next_key, $next_subkey);
}
Try this out, hope this helps
$a = array(
1,
2,
4
);
$b = array(
'foo',
'bar',
'zer'
);
$c = array(
'aaa',
'bbb'
);
$params = array();
$params[] = $a;
$params[] = $b;
$params[] = $c;
$sizeofp = count($params);
for($i=0 ; $i < $sizeofp ; $i++){
foreach ($params[$i] as $paramA) {
for($j=0 ; $j < $sizeofp ; $j++){
if($j == $i){
continue;
}
foreach($params[$j] as $paramB){
echo "\n".$paramA.",".$paramB;
}
}
}
}