How to construct data into a binary tree sort to output a one-dimensional array?
Now that I have constructed the data into a binary tree, how can I recursively solve the binary tree as a one-dimensional array with the following code and data:
Data
$nodes = array(8,3,10,1,6,14,4,7,13);
Construct a binary tree code
function insertNode($node,$newNode){
//var_dump($node);
//var_dump($newNode);
//exit;
if ($node['key'] < $newNode['key']){
if (empty($node['right'])){
$node['right'] = $newNode;
}else{
$node['right'] = insertNode($node['right'],$newNode);
}
}elseif ($node['key'] > $newNode['key']){
if (empty($node['left'])){
$node['left'] = $newNode;
}else{
$node['left'] = insertNode($node['left'],$newNode);
}
}
return $node;
}
function tree($nodes)
{
$node = [
'key' => '',
'left' => '',
'right' => ''
];
$newNode = [
'key' => '',
'left' => '',
'right'=> ''
];
foreach ($nodes as $key => $value){
//insert($value,$key);
if($key == 0)
{
$node['key'] = $value;
continue;
}
$newNode['key'] = $value;
//Constructing a binary tree
$node = insertNode($node,$newNode);
}
//Recursive solution
$node = midSortNode($node);
return $node;
}
var_dump(tree($nodes));
The following is my constructed binary tree
array (size=3)
'key' => int 8
'left' =>
array (size=3)
'key' => int 3
'left' =>
array (size=3)
'key' => int 1
'left' => string '' (length=0)
'right' => string '' (length=0)
'right' =>
array (size=3)
'key' => int 6
'left' =>
array (size=3)
...
'right' =>
array (size=3)
...
'right' =>
array (size=3)
'key' => int 10
'left' => string '' (length=0)
'right' =>
array (size=3)
'key' => int 14
'left' =>
array (size=3)
...
'right' => string '' (length=0)
I need to recursively classify the binary tree into a well-ordered one-dimensional array.
My code is as follows
function midSortNode($node){
$sortArr = [];
if (!empty($node)){
$sortArr[] = midSortNode($node['left']);
//$sortArr['left'] = midSortNode($node['left']);
array_push($sortArr,$node['key']);
$sortArr[] = midSortNode($node['right']);
//$sortArr['right'] = midSortNode($node['right']);
}
return $sortArr;
}
var_dump(midSortNode($node));
Here is the result, but not what I want
0 =>
array (size=3)
0 =>
array (size=3)
0 =>
array (size=0)
...
1 => int 1
2 =>
array (size=0)
...
1 => int 3
2 =>
array (size=3)
0 =>
array (size=3)
...
1 => int 6
2 =>
array (size=3)
...
1 => int 8
2 =>
array (size=3)
0 =>
array (size=0)
empty
1 => int 10
2 =>
array (size=3)
0 =>
array (size=3)
...
1 => int 14
2 =>
array (size=0)
...
How to solve the binary tree as follows
array (size=9)
0 => int 1
1 => int 3
2 => int 4
3 => int 6
4 => int 7
5 => int 8
6 => int 10
7 => int 13
8 => int 14
I'm assuming that your happy with the steps so far, so the main code as it is isn't changed. All I think you need to do is to extract the data from the final tree into a 1 dimensional array. As the items are all leaf nodes and in order, you can just use array_walk_recursive() to go over all of the nodes and add them to a new array...
$tree = tree($nodes);
array_walk_recursive( $tree,
function ($data) use (&$output) { $output[] = $data;} );
print_r($output);
gives...
Array
(
[0] => 1
[1] => 3
[2] => 4
[3] => 6
[4] => 7
[5] => 8
[6] => 10
[7] => 13
[8] => 14
)
Edit:
To update the existing code to do this, you can change the midSortNode() to pass around the list of outputs and only add in the current node...
function midSortNode($node, $sortArr = []){
if (!empty($node)){
$sortArr = midSortNode($node['left'], $sortArr);
$sortArr[] = $node['key'];
$sortArr = midSortNode($node['right'], $sortArr);
}
return $sortArr;
}
Related
What I am trying to get is to remove duplicate values in the Rest field, but I want to assign / keep its date in the original. element:
array (size=413)
0 =>
array (size=5)
'Date' =>
array (size=1)
0 => int 1588520980
'Rest' => 123abc
1 =>
array (size=5)
'Date' =>
array (size=1)
0 => int 1588520981
'Rest' => qwe123
2 =>
array (size=5)
'Date' =>
array (size=1)
0 => int 1588520983
'Rest' => qwe123
I try it but it doesn't work
public function find_repeats($arr)
{
foreach(array_column($arr, 'Rest') as $ckey=>$value) {
$keys = array_reverse(array_keys(array_column($arr, 'Rest'), $value));
foreach ($keys as $v) {
if ($ckey != $v && isset($arr[$v]))
{
$arr[$ckey]['Date'][] = $arr[$v]['Date'][0];
unset($arr[$v]);
}
}
}
return $arr;
}
This is what the table should look like after this operation
array (size=413)
0 =>
array (size=5)
'Date' =>
array (size=1)
0 => int 1588520980
'Rest' => 123abc
1 =>
array (size=5)
'Date' =>
array (size=1)
0 => int 1588520981
1 => int 1588520983
'Rest' => qwe123
Thanks for help! :)
Simple solution without all these stacked functions:
$newData = [];
foreach ($arr as $item) {
$rest = $item['Rest'];
if (!isset($newData[$rest])) {
$newData[$rest] = $item;
} else {
$newData[$rest]['Date'][] = $item['Date'][0];
}
}
// optionally apply array_values to get 0-indexed array:
$newData = array_values($newData);
is there a good way to slice and merge 2 arrays based on empty values for example
first array
0 => string 'Perfect all gorgeous and arrived in less than 1 month for brazil' (length=64)
1 => string '' (length=0)
2 => string '' (length=0)
3 => string 'Good figures for their money, only instead of bits normal stick child bit rastroilsya' (length=85)
4 => string '' (length=0)
5 => string '' (length=0)
second array
0 => string '' (length=0)
1 => string 'http://g01.a.alicdn.com/kf/UTB8jjnecFfFXKJk43Otq6xIPFXaw.jpg" data-eid="eid-201782563197' (length=88)
2 => string 'http://g01.a.alicdn.com/kf/UTB87.bdcNHEXKJk43Jeq6yeeXXaZ.jpg" data-eid="eid-201782563197' (length=88)
3 => string '' (length=0)
4 => string 'http://g01.a.alicdn.com/kf/UTB8cxXwg4HEXKJk43Jeq6yeeXXam.jpg" data-eid="eid-201833045441' (length=88)
5 => string 'http://g04.a.alicdn.com/kf/UTB824Xwg4HEXKJk43Jeq6yeeXXaB.jpg" data-eid="eid-201833045441' (length=88)
I want them to be like this array
array (size=2)
0 =>
array (size=2)
'comment' => string 'Perfect all gorgeous and arrived in less than 1 month for brazil' (length=64)
'images' =>
array (size=2)
0 => string 'http://g01.a.alicdn.com/kf/UTB8jjnecFfFXKJk43Otq6xIPFXaw.jpg" data-eid="eid-201782563197' (length=88)
1 => string 'http://g01.a.alicdn.com/kf/UTB87.bdcNHEXKJk43Jeq6yeeXXaZ.jpg" data-eid="eid-201782563197' (length=88)
1 =>
array (size=2)
'comment' => string 'Good figures for their money, only instead of bits normal stick child bit rastroilsya' (length=85)
'images' =>
array (size=2)
3 => string 'http://g01.a.alicdn.com/kf/UTB8cxXwg4HEXKJk43Jeq6yeeXXam.jpg" data-eid="eid-201833045441' (length=88)
4 => string 'http://g04.a.alicdn.com/kf/UTB824Xwg4HEXKJk43Jeq6yeeXXaB.jpg" data-eid="eid-201833045441' (length=88)
How to do it ?
Got something that will help. It will work with more inputs if you need. It might not work best if your second array has more than one breaking blank. Just working on updated code to solve such issues.
<?php
$arr1 = array("input", "", "", "another input", "", "", "yet another input", "");
$arr2 = array("", "p1", "p2", "", "p01", "p02", "","p11" );
$inp = array("comment" => $arr1, "images" => $arr2);
function mangle_arrays($input) {
$out = array();
$gen = 0;
foreach($input as $key=>$val) {
$id = $gen?-1:0;
if ($gen) {
foreach($val as $v) {
if ($v) {
$out[$id][$key][] = $v;
} else {
$id++;
}
}
} else {
foreach($val as $v) {
if ($v) {
$out[$id] = array();
$out[$id][$key] = $v;
$id++;
}
}
}
$gen++;
}
return $out;
}
// your code goes here
echo "<pre>";
print_r(mangle_arrays($inp));
Results
Array
(
[0] => Array
(
[comment] => input
[images] => Array
(
[0] => p1
[1] => p2
)
)
[1] => Array
(
[comment] => another input
[images] => Array
(
[0] => p01
[1] => p02
)
)
[2] => Array
(
[comment] => yet another input
[images] => Array
(
[0] => p11
)
)
)
I have a php array like this
print_r(myarray) is
Array ( [0] => Array ( [#xsi:nil] => true ) [1] => Array ( [#xsi:nil] => true ) [2] => Array ( [#xsi:nil] => true ) [3] => 'some value' [4] => Array ( [#xsi:nil] => true ))
I need to eliminate the values Array ( [#xsi:nil] => true ) or just to replace them with say "nill". I tried a lot, this being a nested array i couldnt get the key for the values [#xsi:nil] => true
How to check in php for the indexes which hold the value Array ( [#xsi:nil] => true )? and replace them with say 'nill'?
trial one :
$key1 = array_search(array('#xsi:nil'=>'true'), array_column($arrays, 'NOTE')); //to catch the indexes.
function searchMyCoolArray($arrays, $key, $search) {
$count = 0;
foreach($arrays as $object) {
if(is_object($object)) {
$ob1 = $object;
$object = get_object_vars($object);
$key1 = array_search(40489, array_column($arrays, 'uid'));
}
if(array_key_exists($key, $object) && $object[$key] == $search)
{
// print_r($first_names_note[$key]);
// echo "ffgfg ".$ob1[0]." rtrtrt";
// var_dump($object);
// print_r($arrays[$key]);
// echo $object;
// print_r($object);
// print_r($first_names_note)."<br>";
$count++;
//echo "sddsdsdsd";
}
}
return $count;
}
echo searchMyCoolArray($first_names_note, '#xsi:nil', 'true');
here i got the count correct, but it was not i need, I tried to get the indexs in the function itself, but failed
Please help, i googled alot pleeeeeeeeeeeeeeeeez
You may try to use array_walk to traverse the array and then unset all elements with the key #xsi:nil like this:
<?php
$arr = array(
array("#xsi:nil" => true),
array("#xsi:nil" => true),
array("#xsi:nil" => true),
array("some_value" =>4),
array("#xsi:nil" => true),
);
array_walk($arr, function(&$data){
if(is_array($data) && array_key_exists("#xsi:nil", $data)){
unset($data["#xsi:nil"]);
$data[] = "nil";
}
});
var_dump($arr);
// IF YOU WANT TO REMOVE ALL EMPTY ARRAYS COMPLETELY, JUST DO THIS:
$arr = array_filter($arr);
var_dump($arr);
// GET THE LENGTH OF THE FILTERED ARRAY.
$count = count($arr);
echo $count; //<== PRODUCES 5
// THE 1ST VAR_DUMP() PRODUCES:
array (size=5)
0 =>
array (size=1)
0 => string 'nil' (length=3)
1 =>
array (size=1)
0 => string 'nil' (length=3)
2 =>
array (size=1)
0 => string 'nil' (length=3)
3 =>
array (size=1)
'some_value' => int 4
4 =>
array (size=1)
0 => string 'nil' (length=3)
// THE 2ND VAR_DUMP() PRODUCES:
array (size=5)
0 =>
array (size=1)
0 => string 'nil' (length=3)
1 =>
array (size=1)
0 => string 'nil' (length=3)
2 =>
array (size=1)
0 => string 'nil' (length=3)
3 =>
array (size=1)
'some_value' => int 4
4 =>
array (size=1)
0 => string 'nil' (length=3)
Test it out HERE.
Cheers & Good Luck...
This is not the answer, the code for the answer was provided by #Poiz
Here is my complete code which i formatted
//my array
$arr = Array (Array ( '#xsi:nil' => 'true' ), Array ('#xsi:nil' => 'true' ), Array ( '#xsi:nil' => 'true' ) );
// print_r($arr);
//performed array walk
array_walk($arr, function(&$data){
if(is_array($data) && array_key_exists("#xsi:nil", $data)){
unset($data["#xsi:nil"]);
$data = "nil";
}
});
print_r($arr);
//OUTPUT : Array ( [0] => nil [1] => nil [2] => nil )
From this foreach:
foreach ($statisticheProdotti as $values) {
$prod[] = $values['nome'];
$nomi = array_values(array_unique($prod, SORT_REGULAR));
$arr = array_combine(range(1, 12), range(1, 12));
foreach ($arr as $key => $val) {
$data = ($val == $values['mese']) ? $values['data'] : 0;
$arr[$val] = $data;
}
$prodotti[] = ['name' => $values['nome'], 'data' => array_values($arr)];
}
I get this array:
array (size=14)
0 =>
array (size=2)
'name' => string 'COMBIART PLUS' (length=13)
'data' =>
array (size=12)
0 => string '92' (length=2)
1 => int 0
2 => int 0
3 => int 0
4 => int 0
5 => int 0
6 => int 0
7 => int 0
8 => int 0
9 => int 0
10 => int 0
11 => int 0
1 =>
array (size=2)
'name' => string 'COMBIART PLUS' (length=13)
'data' =>
array (size=12)
0 => int 0
1 => int 0
2 => int 0
3 => int 0
4 => int 0
5 => int 0
6 => int 0
7 => int 0
8 => int 0
9 => int 0
10 => int 0
11 => string '92' (length=2)
2 =>
array (size=2)
'name' => string 'SECUR' (length=10)
'data' =>
array (size=12)
0 => string '5' (length=1)
1 => int 0
2 => int 0
3 => int 0
4 => int 0
5 => int 0
6 => int 0
7 => int 0
8 => int 0
9 => int 0
10 => int 0
11 => int 0
3 =>
.....`
I need to remove duplicated name and have unique array data.
Final output should be (example from index 0 and 1 which have same 'name'):
['name' => 'COMBIART PLUS', 'data' => [92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92]].
I hope I've well explained my problem.
Thanks
Sorry it's taken me a while to respond to this.
This might not be the most elegant way to do this, but assuming you want to combine the arrays with the same name, and combine the data array to make a unique array by using the values and the keys (assuming zero is not useful here), you can do something like this:
$output = array();
foreach ($example as $data) {
// Use the name as a quick array key reference to avoid having to search a second level of the array
$key = $data['name'];
if (!array_key_exists($key, $output)) {
// Instantiate the first entry using the name as the array key (we can reset this later)
$output[$key] = array(
'name' => $key,
'data' => $data['data']
);
// Skip the rest of this loop
continue;
}
// An entry already exists for the name, so merge any unique values into the array using the
// keys AND values to determine if something is unique. Zero is treated as empty.
foreach ($data['data'] as $newKey => $newValue) {
if (empty($output[$key]['data'][$newKey])) {
// Add a new unique entry to the output array (zero counts as empty here)
$output[$key]['data'][$newKey] = $newValue;
}
}
}
// Remove the name from the keys now
$output = array_values($output);
This should give you the result you're after. Example here.
thanks for your help scrowler, thanks to your code I have been able to get what I needed but I've just changed something to adapt it to my project...
function generateChartData($array) {
$prodArr = [];
$oldProd = '';
$arr = array_fill(0, 12, 0);
foreach ($array as $values) {
$Prod = $values['name'];
if ($Prod !== $oldProd) {
if (!empty($oldProd)) {
$prodotti[] = ['name' => $oldProd, 'data' => $arr];
}
$oldProd = $Prod;
}
foreach ($arr as $key => $val) {
if ($key == $values['mese'] - 1) {
$arr[$key] = (int) $values['data'];
}
}
}
// get last item
if (!empty($oldProd)) {
$prodArr[] = ['name' => $oldProd, 'data' => $arr];
}
return $prodArr;
}
I have a question about correct and fast seeking in php array.
I have input array:
array (size=2)
0 =>
array (size=7)
'Videos' =>
array (size=2)
240 =>
array (size=2)
...
120 =>
array (size=2)
...
'Texts' =>
array (size=0)
empty
'Price' => float 0
'QaAudio' => int 1
'QaVideo' => int 3
'Level' => string 'normal' (length=6)
'PreviewPic' =>
array (size=7)
40 =>
array (size=12)
...
60 =>
array (size=12)
...
140 =>
array (size=12)
...
160 =>
array (size=12)
...
320 =>
array (size=12)
...
640 =>
array (size=12)
...
1024 =>
array (size=12)
...
1 =>
array (size=7)
'Videos' =>
array (size=3)
480 =>
array (size=2)
...
360 =>
array (size=2)
...
120 =>
array (size=2)
...
'Texts' =>
array (size=0)
empty
'Price' => float 0
'QaAudio' => int 1
'QaVideo' => int 3
'Level' => string 'sexy' (length=4)
'PreviewPic' =>
array (size=7)
40 =>
array (size=12)
...
60 =>
array (size=12)
...
140 =>
array (size=12)
...
160 =>
array (size=12)
...
320 =>
array (size=12)
...
640 =>
array (size=12)
...
1024 =>
array (size=12)
...
I need to find in it the video, that has max value in Videos key.(it has 360,240,120 values as you can see in example) and has Level Key that equal to 'normal' or 'sexy' value.
I wrote some method to do it:
public function getPresentationVideo($id)
{
$result = [];
$notHardVideos = [];
$profileVideos = $this->getProfilesVideos($id,0,50);
if ($profileVideos && count($profileVideos) > 0) {
foreach ($profileVideos as $video) {
if (in_array($video['Level'],['normal','sexy'])) {
$video['maxVideoQuality'] = max(array_keys($video['Videos']));
$notHardVideos[] = $video;
}
}
$keyForMaxQuality = 0;
if (count($notHardVideos) > 1) {
$maxQuality = 0;
foreach($notHardVideos as $key => $video) {
if($video['maxVideoQuality'] > $maxQuality)
{
$maxQuality = $video['maxVideoQuality'];
$keyForMaxQuality = $key;
}
}
}
if (count($notHardVideos) > 0) {
$result = $notHardVideos[$keyForMaxQuality];
unset($result['maxVideoQuality']);
}
}
return $result;
}
It do it well.
But i wonder is there any more effective way to do it.
Do you have any ideas?
Thanks in advance.
$result = array_reduce($videos, function ($result, array $video) {
if (!in_array($video['Level'], ['normal', 'sexy'])) {
return $result;
}
if (!$result) {
return $video;
}
if (max(array_keys($video['Videos'])) > max(array_keys($result['Videos']))) {
return $video;
}
return $result;
});
This will return the sub array which has a 'normal' or 'sexy' level (BTW, FTW?!) and which has the highest key in its 'Videos' sub array. It doesn't include any other considerations, as you seem to have in your code, because you did not specify exactly what those considerations are. However, you should get the idea and can add more checks if you need.
See http://php.net/array_reduce for help with this function. In short, this takes each element in the array in turn and compares it to the previous best candidate. I.e., $result will be nothing at first, but when you have found a 'normal' or 'sexy' video it will become that video, and on subsequent calls the video with the higher keys will win.