This function should iterate through multidimensional array and return collection of array's element_rule_id values. Hovewer it's not returning anything.
You can check var_dump of array here: http://pastebin.com/T5nwGmna
function deepIns($array = array(), $collect = array(), $str = '') {
$count = count($array);
foreach($array as $i => $val) {
if(is_array($val)) {
if(array_key_exists('element_rule_id' ,$val)) {
$collect[$val['element_rule_id']] = 1;
}
if(($count - 1) == $i) {
if(array_key_exists('0', $val['condition'])) {
deepIns($val['condition'], $collect);
}
else {
return $collect;
}
}
}
}
}
Expected result would be:
array (size=5)
'rule_demo_rules1_1' => int 1
'rule_demo_rules1_2' => int 1
'rule_demo_rules1_3' => int 1
'rule_demo_rules1_5' => int 1
'rule_demo_rules1_6' => int 1
In desining of recursive functions, returning is ambigous way, simple solution is to put your function in an static class, and add the return results into that class:
class xx {
public static $result;
function deepIns($array = array(), $collect = array(), $str = '') {
$count = count($array);
foreach($array as $i => $val) {
if(is_array($val)) {
if(array_key_exists('element_rule_id' ,$val)) {
$collect[$val['element_rule_id']] = 1;
}
if(($count - 1) == $i) {
if(array_key_exists('0', $val['condition'])) {
deepIns($val['condition'], $collect);
}
else {
self::$result[] = $collect;
}
}
}
}
}
All is needed was $collection before deepIns($val['condition'], $collect);
$collection = deepIns($val['condition'], $collect);
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'm trying to solve a somewhat simple task but can't wrap my head around doing it without a lot of loops and messy code.
I want all to print all combinations of the array below:
$product = array(
array
(
'1X'
),
array
(
'X2'
)
);
producing the following result:
//ROW 1
1
X
//ROW 2
X
2
//ROW 3
1
2
//ROW 4
X
X
this work:
$product = array(
array
(
'1WQ'
),
array
(
'3'
),
array
(
'X'
)
);
//
class Combine{
private $product = array();
private $result = array();
private $format = array();
public function __construct($p=array()){
$this->product = $p;
}
public function process(){
foreach($this->product as $k=>$v){
$this->format[] = str_split($v[0]);
}
$this->result = $this->build();
return $this;
}
public function build()
{
if (!$this->format) {
return array(array());
}
$sub = array_shift($this->format);
$c = $this->build($this->format);
$res = array();
foreach ($sub as $v) {
foreach ($c as $p) {
array_unshift($p, $v);
$res[] = $p;
}
}
return $res;
}
public function response(){
return $this->result;
}
}
//
$combine = new Combine($product);
$resp = $combine->process()->response();
var_dump($resp);
function helperFunction($array, $index, $workArray)
{
$tempArray = array();
$tmpStr = $array[$index][0];
// loop over the current array characters
for( $i = 0; $i < strlen($tmpStr); $i++ )
{
$char = substr($tmpStr, $i, 1);
// first time - add characters to the work array
if (count($workArray) == 0)
{
$tempArray[] = $char;
}
// later round - add characters to existing items
else
{
foreach ($workArray as $workItem)
{
$tempArray[] = $workItem . $char;
}
}
}
// last round
if (count($array) == $index + 1)
{
return $tempArray;
}
// recursion round
else
{
return helperFunction($array, $index + 1, $tempArray);
}
}
$result = helperFunction($product, 0, array());
I'm constructing a gallery which will use the URI to define a set of filter settings. CodeIgniter's ruri_to_assoc() works brilliantly for the majority of my settings as they are as simple as key=>value. However, one value (tags) can contain a number of values that I wish to match against.
As ruri_to_assoc() works off a key/val pairing, how would I set an array to a key in the url? Example:
/days/365/order/oldest/tag/car/tag/red/tag/mustang
At the moment, it looks like I'm going to have to explode the uri_string() and cycle through it myself. Like so:
$test_fil = explode('/',$this->uri->uri_string());
unset($test_fil[0]);
$val = 'key';
foreach($test_fil as $fkey=>$fval){
if($fval=='tags'){
$val = 'tag';
$new_filter['tags'] = '';
}
else{
if($val == 'key'){
$new_filter[$fval] = '';
$val = 'val';
$current_key = $fval;
}
elseif($val == 'val'){
$new_filter[$current_key] = $fval;
$val = 'key';
}
else{
$new_filter['tags'][] = $fval;
}
}
}
Is there something in CI that can do this for me?
We just need to make sure that uri_to_assoc will not override already existing keys when building the array.
In application/core create MY_URI.php :
class MY_URI extends CI_URI
{
protected function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
{
if ( ! is_numeric($n))
{
return $default;
}
if (isset($this->keyval[$which], $this->keyval[$which][$n]))
{
return $this->keyval[$which][$n];
}
$total_segments = "total_{$which}s";
$segment_array = "{$which}_array";
if ($this->$total_segments() < $n)
{
return (count($default) === 0)
? array()
: array_fill_keys($default, NULL);
}
$segments = array_slice($this->$segment_array(), ($n - 1));
$i = 0;
$lastval = '';
$retval = array();
foreach ($segments as $seg)
{
/*HERE IS THE PART WE TRULY OVERRIDE*/
if ($i % 2)
{
if(is_array($retval[$lastval]))
$retval[$lastval][] = $seg;
else
$retval[$lastval] = $seg;
}
else
{
if(isset($retval[$seg]) && !is_array($retval[$seg]))
{
$tmp = $retval[$seg];
$retval[$seg] = array();
$retval[$seg][] = $tmp;
}
else if(!isset($retval[$seg]))
{
$retval[$seg] = NULL;
$lastval = $seg;
}
}
/*END OVERRIDE*/
$i++;
}
if (count($default) > 0)
{
foreach ($default as $val)
{
if ( ! array_key_exists($val, $retval))
{
$retval[$val] = NULL;
}
}
}
// Cache the array for reuse
isset($this->keyval[$which]) OR $this->keyval[$which] = array();
$this->keyval[$which][$n] = $retval;
return $retval;
}
}
And then in your controller, nothing change :
$myTags = $this->uri->uri_to_assoc();
Here is what I get after testing :
array (size=3)
'days' => string '365' (length=3)
'order' => string 'oldest' (length=6)
'tag' =>
array (size=3)
0 => string 'car' (length=3)
1 => string 'red' (length=3)
2 => string 'mustang' (length=7)
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 want an easy way to count a number of times the string "Apple" has present in the given
# My Array :
$arr = array(
1 => "Apple",
2 => "Orange",
3 => array(1=>"Bananna",2=>"Apple"),
4 => "Grape",
5 => "Apple",
6 => array(1=>"Grape"),
7 => "Orange");
# Want to count only "Apple"
$needle = "Apple";
# My Function :
function arrsearch($needle,$haystack,$return) {
if(!is_array($haystack)) {
return false;
}
foreach($haystack as $key=>$val) {
if(is_array($val)) {
$return = arrsearch($needle,$val,$return);
}else if(strtolower($val) == strtolower($needle)) {
$return[] = $key;
}
}
return $return;
}
$var = arrsearch("Apple",$arr,array());
echo " Output : ".count($var);
# Output : 3
I used the above function to find the number of times the string "Apple" in the array. Suggest me the best one.
You could use array_walk_recursive:
function search_for($arr, $term)
{
$count = 0;
array_walk_recursive($arr, function($item, $idx, $term) use (&$count) {
if (false !== stripos($item, $term)) {
++$count;
}
}, $term);
return $count;
}
search_for($arr, 'Apple'); // returns 3
The expression function($item, $idx, $term) use (&$count) { .. } is an anonymous function declaration; it works just like a regular function, but you can inherit variables from the parent scope by using use ($var) or use (&$var) if you need to modify it too. More examples can be found on the manual page.
Update
For versions of PHP < 5.3, you'd have to encapsulate the counter using objects:
class RecursiveArraySearcher
{
private $c = 0;
public static function find($arr, $term)
{
$obj = new self;
array_walk_recursive($arr, array($obj, 'ismatch'), $term);
return $obj->c;
}
public function ismatch($item, $key, $term)
{
if (false !== stripos($item, $term)) {
++$this->c;
}
}
}
echo RecursiveArraySearcher::find($arr, 'Apple'); // 3
You can use a recursive function like this ..
function finditem($item,$array){
$count = 0;
foreach($array as $key => $value){
if(is_array($value) == true){
$countx = finditem($item,$value);
$count = $count + $countx;
}else if($value == $item)
$count++;
}
return $count;
}
echo finditem("Apple",$arr);
Hope it helps.
Another solution is to flat the array and count the values:
<?php
function search_for($arr, $term) {
$flatten_array = array();
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
foreach($it as $v) {
$flatten_array[] = $v;
}
$count_values = array_count_values($flatten_array);
return $count_values[$term];
}
echo search_for($arr, 'Apple'); // print 3