I'm trying to build a tree-map from categories. I have the categories (I have a lot of categories and I want to remove duplicates and show them in a tree-map view with count) and I have the following code:
<?php
$cat = array(
"Sneakers/Men",
"Sneakers/Women",
"Accessories/Jewellery/Men",
"Accessories/Jewellery/Men",
"Accessories/Jewellery/Women",
"Accessories/Jewellery/Men/Bvlgari"
);
$out = [];
foreach ($cat as $str) {
$lookup = &$out;
$parts = explode("/", $str);
foreach ($parts as $part) {
$lookup = &$lookup[$part];
if (!isset($lookup))
$lookup = [];
if ($part == end($parts))
$lookup = is_array($lookup) ? 1 : ++$lookup;
}
}
print_r($out);
OUTPUT:
Array
(
[Sneakers] => Array
(
[Men] => 1
[Women] => 1
)
[Accessories] => Array
(
[Jewellery] => Array
(
[Men] => 3
[Women] => 1
)
)
)
I would like to be:
Array
(
[Sneakers] => Array
(
[Men] => 1
[Women] => 1
)
[Accessories] => Array
(
[Jewellery] => Array
(
[Men] => Array (
[Bvlgari] => 1
)
[Women] => 1
)
)
)
You're losing information with both of those formats and the suggested answer is not going to cut it. You do need recursion and each item needs to hold a count and children.
$cat_paths = [
'Sneakers/Men',
...
];
$cat_counts = $item = [# template of each item
'count' => 0,
'children' => [],
];
foreach ($cat_paths as $cat_path) {
$level = &$cat_counts;# use a reference for recursion
if ($cat_path) {# allow uncategorized to be in root of tree
$cat_path = explode('/', $cat_path);
do {
$cat = array_shift($cat_path);
if (!isset($level['children'][$cat])) {
$level['children'][$cat] = $item;
}
$level = &$level['children'][$cat];# step down into tree
} while ($cat_path);
}
$level['count']++;
}
unset($level);
Related
{"id":34,"first_name":"xus"}
{"id":34,"first_name":"xus"}
{"id":4,"first_name":"ABC"}
{"id":4,"first_name":"ABC"}
$newlist = [];
$values = [];
foreach ($appointment_list as $key => $value) {
# code...
$values[] = $value['users'];
foreach($values as $val){
$newlist[$val->id]=$values;
}
unset($newlist[$key][$values]);
}
I want to remove duplicate value from object show distinct value base on id and want to count duplicate exist of each id
Expected
id 34 has 2 duplicate
and it should return one object
{"id":34,"first_name":"xus", "count":2}
something like that
You can use array_reduce
$arr = array(
array("id" => 34,"first_name" => "xus"),
array("id" => 34,"first_name" => "xus"),
array("id" => 4,"first_name" => "ABC"),
array("id" => 4,"first_name" => "ABC"),
);
$result = array_reduce($arr, function($c, $v){
if ( !isset( $c[$v["id"]] ) ) {
$c[$v["id"]] = $v;
$c[$v["id"]]["count"] = 1;
} else {
$c[$v["id"]]["count"]++;
}
return $c;
}, array());
$result = array_values( $result );
echo "<pre>";
print_r( $result );
echo "</pre>";
This will result to:
Array
(
[0] => Array
(
[id] => 34
[first_name] => xus
[count] => 2
)
[1] => Array
(
[id] => 4
[first_name] => ABC
[count] => 2
)
)
The simplest way of doing this is to create an empty array and map your objects using "id" as a key.
Here's the working snippet
<?php
$objectsRaw = [];
$objectsRaw[] = '{"id":34,"first_name":"xus"}';
$objectsRaw[] = '{"id":34,"first_name":"xus"}';
$objectsRaw[] = '{"id":4,"first_name":"ABC"}';
$objectsRaw[] = '{"id":4,"first_name":"ABC"}';
# decode the json objects into PHP arrays
$objects = array_map(
function($objectJson) {
$object = json_decode($objectJson, true);
return $object;
},
$objectsRaw
);
# map the objects
$result = [];
foreach($objects as $object) {
if (array_key_exists($object['id'], $result) === false) {
$object['count'] = 1;
$result[$object['id']] = $object;
continue;
}
$result[$object['id']]['count']++;
}
# encode result
$resultRaw = array_map('json_encode', $result);
# would look like
# Array
# (
# [34] => {"id":34,"first_name":"xus","count":2}
# [4] => {"id":4,"first_name":"ABC","count":2}
# )
# reset array keys (if you need this)
$resultRaw = array_values($resultRaw);
# would look like
# Array
# (
# [0] => {"id":34,"first_name":"xus","count":2}
# [1] => {"id":4,"first_name":"ABC","count":2}
# )
Have array like this
Array
(
[0] => Array
(
[CategoriesName_1] => Happy Birthday
[CategoriesName_2] => Flowers
[CategoriesName_3] => Fruit baskets
[CategoriesDescription_1] =>
[CategoriesDescription_2] =>
[CategoriesDescription_3] => Fruit baskets descr
[CategoriesUrl_1] => happy-birthday
[CategoriesUrl_2] => flowers
[CategoriesUrl_3] => fruit-baskets
)
)
Want to convert it to array like this (need to get this result)
Array
(
[0] => Array
(
[CategoriesName] => Happy Birthday
[CategoriesDescription] =>
[CategoriesUrl] => happy-birthday
)
[1] => Array
(
[CategoriesName] => Flowers
[CategoriesDescription] =>
[CategoriesUrl] => flowers
)
[2] => Array
(
[CategoriesName] => Fruit baskets
[CategoriesDescription] => Fruit baskets descr
[CategoriesUrl] => fruit-baskets
)
)
The initial (one dimensional array) have keys CategoriesName_1, CategoriesUrl_1, CategoriesDescription_1. For each number (_1, _2, _3) want to put name, url and description together and create separate subarray.
At first created 3 separate arrays
foreach ( $array_with_breadcrumbs[0] as $key_brcr => $val_brcr ) {
if( 'CategoriesUrl_' == substr($key_brcr,0,14) ){
$array_url_brcr[] = array( 'CategoriesUrl' => $val_brcr );
}
if( 'CategoriesName_' == substr($key_brcr,0,15) ){
$array_name_brcr[] = array( 'CategoriesName' => $val_brcr );
}
if( 'CategoriesDescription_' == substr($key_brcr,0,22) ){
$array_description_brcr[] = array( 'CategoriesDescription' => $val_brcr );
}
}//foreach ( $array_with_breadcrumbs[0] as $key_brcr => $val_brcr ) {
Then loop through all three arrays like this
foreach( $array_url_brcr as $i_url => $val_url ){
foreach( $array_name_brcr as $i_name => $val_name ){
foreach( $array_description_brcr as $i_description => $val_description ){
if( $i_url == $i_name ) {
$combined_arr_brcr[] = array(
'CategoriesUrl' => $val_url['CategoriesUrl'],
'CategoriesName' => $val_name['CategoriesName'],
'CategoriesDescription' => $val_description['CategoriesDescription']
);
}
}
}
}
I get nine (3 arrays * 3 loops) subarrays with not expected results. From the results I must write additional code where I take (keep) first, fifth and ninth subarray.
Code appears very long. Is there any better (shorter, simpler) way to get result?
$final_array=array();
for ($i=0; $i < 3; $i++) {
$k=$i+1;
$final_array[$i]=array(
'CategoriesName'=>$array_with_breadcrumbs[0]['CategoriesName_'.$k],
'CategoriesDescription'=>$array_with_breadcrumbs[0]['CategoriesDescription_'.$k],
'CategoriesUrl'=>$array_with_breadcrumbs[0]['CategoriesUrl_'.$k],
);
}
print_r($final_array);
if the number of keys is more than 3 , you can use this
$final_array=array();
$no_of_keys=3; //change the value of number of keys
$vars=array('CategoriesName','CategoriesDescription','CategoriesUrl'); // add variables
for ($i=0; $i < $no_of_keys; $i++) {
$k=$i+1;
$final_array[$i]=array();
foreach ($vars as $var) {
$final_array[$i][$var]=$array_with_breadcrumbs[0][$var."_".$k]
}
}
print_r($final_array);
$source = $array_with_breadcrumbs[0];
$result = [];
for ($i = 1; $i <= 3; $i++)
{
array_push($result,
[
'CategoriesName' => $source['CategoriesName_' . $i],
'CategoriesDescription' => $source['CategoriesDescription_' . $i],
'CategoriesUrl' => $source['CategoriesUrl_' . $i]
]);
}
var_dump($result);
The result of a query in my database returns something like this (a record for each row):
1.
1.1.
1.1.01.
1.1.01.001
1.2.
1.2.01.
1.2.02.
I'm trying to create something that returns me a multidimensional array in a tree format, like this:
array(
'1.' => array(
'1.1' => array(
'1.1.01.' => array(
(int) 0 => '1.1.01.001'
)
),
'1.2' => array(
(int) 0 => '1.2.01.',
(int) 1 => '1.2.02.'
)
)
)
All I could think to do was reverse the order of elements using explode().
I appreciate any suggestions.
Your format is very tricky because of :
1.2.
1.2.01. |
1.2.02. V Making this array instead of value
You can try
$string = "1.
1.1.
1.1.01.
1.1.01.001
1.2.
1.2.01.
1.2.02.";
$array = explode("\n", $string);
$data = array();
$temp = &$data;
$it = new CachingIterator(new ArrayIterator($array), CachingIterator::FULL_CACHE);
$continue = false;
foreach ( $it as $v ) {
$v = trim($v);
if ($it->hasNext()) {
$next = trim($it->getInnerIterator()->current());
if (stripos($next, $v) === 0) {
$temp = &$temp[$v];
} else {
$temp[] = $v;
if (strlen($next) != strlen($v)) {
$temp = &$data;
}
}
} else {
$temp[] = $v;
}
}
print_r($data);
Output
Array
(
[1.] => Array
(
[1.1.] => Array
(
[1.1.01.] => Array
(
[0] => 1.1.01.001
)
)
)
[1.2.] => Array
(
[0] => 1.2.01.
[1] => 1.2.02.
)
)
Here is a move COMPLEX demo
I have this array.
Array
(
[name] => Array
(
[isRequired] => 1
[isBetween] => 1
[isAlphaLower] =>
[isLength] =>
)
[email] => Array
(
[isEmail] => 1
)
[pPhone] => Array
(
[isPhone] =>
)
)
i want to split the array into two.
1. array with all boolean value true
Array
(
[name] => Array
(
[isRequired] => 1
[isBetween] => 1
)
[email] => Array
(
[isEmail] => 1
)
)
2. array with all boolean value false
Array
(
[name] => Array
(
[isAlphaLower] =>
[isLength] =>
)
[pPhone] => Array
(
[isPhone] =>
)
)
How do i do it?
thank you..
initialize the two new arrays
foreach the input array
foreach the inner array of each input array entry
according to the value set the one or the other of the two new arrays
done.
Example:
$arrayTrue = $arrayFalse = arrray(); # 1
foreach($arrayInput as $baseKey => $inner) # 2
foreach($inner as $key => $value) # 3
if ($value) $arrayTrue[$basekey][$key] = $value; # 4
else $arrayFalse[$basekey][$key] = $value;
function is_true($var) {
return $var;
}
function is_false($var) {
return !$var;
}
$result_true = array();
$result_false = array();
foreach ($array as $k => $a) {
$result_true[$k] = array_filter($a, 'is_true');
$result_false[$k] = array_filter($a, 'is_false');
};
or
$result_true = array();
$result_false = array();
foreach ($array as $k => $a) {
$result_true[$k] = array_filter($a);
$result_false[$k] = array_filter($a, function ($x) { return !$x; } );
};
As your array is a 2 level array, you will need to use 2 loops.
$trueValues = array();
$falseValues = array();
foreach($input AS $key=>$firstLevelValue) {
foreach($firstLevelValue AS $key2=>$secondLevelValue) {
if ($secondLevelValue)
$trueValues[$key][$key2] = $secondLevelValue;
else
$falseValues[$key][$key2] = $secondLevelValue;
}
}
A 3 level array would be:
$trueValues = array();
$falseValues = array();
foreach($input AS $key=>$firstLevelValue) {
foreach($firstLevelValue AS $key2=>$secondLevelValue) {
foreach($secondLevelValue AS $key3=>$thirdLevelValue) {
if ($thirdLevelValue)
$trueValues[$key][$key2][$key3] = $thirdLevelValue;
else
$falseValues[$key][$key2][$key3] = $thirdLevelValue;
}
}
}
After a rollercoaster ride, I am "this" close to finalising a script I have been working on.
I have a multi-dimensional array stored in $newarray as below. I have built this array myself so the code to build it can be changed if needs be. But after creation I then loop through it picking out the values I want. I build a new array for each key in the upper array (3 in this case, 111, 222 & 333) and populate each with a a bunch of data objects from next array key down along with some other data.
However, what I need in the case below is to generate each of the 3 arrays (111, 222, 333) twice, once where the final array value = 0 ($the_action) and once where it = '1'. Where it = 1, print it, else where it = 0, do something else.
I also think that the way I loop through arrays with a single value in it is probably not very efficient, and the same goes for using key names as values.
Grateful for any help.
Array
(
[111] => Array
(
[1234] => Array
(
[100000] => Array
(
[20000] => 0
)
)
[1244] => Array
(
[100001] => Array
(
[20001] => 1
)
)
[1255] => Array
(
[100002] => Array
(
[20002] => 1
)
)
)
[222] => Array
(
[1233] => Array
(
[100013] => Array
(
[20013] => 0
)
)
[1241] => Array
(
[100014] => Array
(
[20014] => 1
)
)
)
[333] => Array
(
[15633] => Array
(
[100026] => Array
(
[20026] => 0
)
)
[12144] => Array
(
[100028] => Array
(
[20028] => 0
)
)
)
)
Code to build $newarray ($stack comes from CSV with 5 columns):
$newarray = array();
foreach($stack as $val){
$lineid = $val[0]; $segmentid = $val[1]; $action = $val[2]; $recency = $val[3]; $frequency = $val[4];
$newarray[$lineid][$segmentid][$recency][$frequency] = $action;
}
Code to loop through array:
foreach($newarray as $key => $value) {
$target_pixels = array();
$owner_id = $key;
foreach($value as $key2 => $value2){
$target_pixel = new stdClass;
$target_pixel->conversion_id = $key2;
$target_pixel->negated = false;
foreach($value2 as $key3 => $value3){
$target_pixel->seconds_since_conversion = $key3 * 24 * 60 * 60;
foreach($value3 as $key4 => $value4){
$target_pixel->frequency_min = $key4;
$the_action = $value4;
}
}
$target_pixels[] = $target_pixel;
}
print_r($target_pixels);
}
Since you say you can change the structure of the array, I would go with something along the lines of:
$newarray = array();
foreach($stack as $val){
$lineid = $val[0];
$segmentid = $val[1];
$action = $val[2];
$recency = $val[3];
$frequency = $val[4];
$newarray[$lineid][$segmentid] = array(
'recency' => $recency,
'frequency' => $frequency
'action' => $action
);
}
Then your code would look like:
foreach ($newarray as $lineid => $line) {
$target_pixels = array();
$owner_id = $lineid;
foreach ($line as $segmentid => $segment){
$target_pixel = new stdClass;
$target_pixel->conversion_id = $segmentid;
$target_pixel->negated = false;
$target_pixel->seconds_since_conversion = $segment['recency'] * 24 * 60 * 60;
$target_pixel->frequency_min = $segment['frequency'];
$target_pixels[$segment['action']][] = $target_pixel;
}
var_dump($target_pixels);
}