php convert flat family list to tree - php

this one is a little Q&A-style...
i've been searching for this situation and couldn't find any solution, so i build my own.
it took me a few days to get a working code for my needs, but now i am wondering if there's a more efficient way:
$data = [
['a','aa','aaa'],
['a','aa','aab'],
['a','aa','aac'],
['a','ab'],
['a','ac','aca'],
['b','ba'],
['b','bb'],
['b','bc'],
];
function tree($values){
$on_end = sizeof($values) == 1 && sizeof($values[0]) == 0;
if ( $on_end ) return null;
$tree1 = [];
$tree2 = [];
foreach ($values as $a){
$parent = $a[0];
//remove the first column
array_shift($a);
$tree1[ $parent ][] = $a;
}
foreach ($tree1 as $parent => $b){
$tree2[ $parent ] = tree( $b );
}
return $tree2;
}
echo "<pre>".print_r(tree($data),true)."</pre>";
this is the result:
Array
(
[a] => Array
(
[aa] => Array
(
[aaa] =>
[aab] =>
[aac] =>
)
[ab] =>
[ac] => Array
(
[aca] =>
)
)
[b] => Array
(
[ba] =>
[bb] =>
[bc] =>
)
)
if anybody got a better one, please post it!

You have a shortest solution ... but it's using eval function erk
<?php
$data = [
['a','aa','aaa'],
['a','aa','aab'],
['a','aa','aac'],
['a','ab'],
['a','ac','aca'],
['b','ba'],
['b','bb'],
['b','bc'],
];
function arrayToTree_eval(array $source, $defaultValue = null) {
$tree = [];
foreach( $source as $values ) {
eval(sprintf('$tree%s = $defaultValue;', '["' . implode('"]["', $values) . '"]'));
}
return $tree;
}
var_dump( arrayToTree_eval($data) );
7 lines of code, and hop !
array (size=2)
'a' =>
array (size=3)
'aa' =>
array (size=3)
'aaa' => null
'aab' => null
'aac' => null
'ab' => null
'ac' =>
array (size=1)
'aca' => null
'b' =>
array (size=3)
'ba' => null
'bb' => null
'bc' => null
:)

Related

how to get array with unique values in laravel/php

I need to merge arrays into 1 array but what I need is to remove before the main data they b oth have in common (duplicated values i mean), I need only unique values when merged.
array formed from foreach.
public $arrayfields= [];
public $itemMap = [];
public function getRowMapping(array $row,$uniqueField,$moduleName)
{
$arrayData = [];
foreach ($this->columnMapping as $key => $value) {
$row = $this->moduleType($key,$value,$row,$moduleName);
}
$unique = $row[$uniqueField];
if(!isset($this->itemMap[$unique])){
$this->itemMap[$unique] = $row;
$this->itemMap[$unique][$unique]['items'] = [];
}
$this->itemMap[$unique]['items'][] = $row['items'];
return $row;
}
i changed little bit to my input
How can i do that?
so now the input will be like this
Array
(
[bill_type] => 1
[bill_number] => BIL-003
[order_number] => ON-003
[items] => Array
(
[track_inventory] => 0
[sku1] => sku1
[name] => Kidswear1
)
)
Array
(
[bill_type] => 1
[bill_number] => BIL-003
[order_number] => ON-003
[items] => Array
(
[track_inventory] => 0
[sku1] => sku2
[name] => Pant
)
)
Array
(
[bill_type] => 1
[bill_number] => BIL-002
[order_number] => ON-002
[items] => Array
(
[track_inventory] => 0
[sku1] => sku3
[name] => Pants
)
)
The final output I'm looking for is
Array
(
[BIL-003] => Array
(
[bill_type] => 1
[order_number] => ON-003
[items] => Array
(
[0] => Array(
[track_inventory] => 0
[sku1] => sku1
[name] => Kidswear1
)
[1] => Array
(
[track_inventory] => 0
[sku1] => sku2
[name] => Pant
)
)
[BIL-002] => Array
(
[bill_type] => 1
[order_number] => ON-002
[items] => Array
(
[0] => Array(
[track_inventory] => 0
[sku1] => sku3
[name] => pants
)
)
)~~~
I think there is no standard library function to accomplish this.
So here is the function that accomplishes this:
function merge($array1, $array2)
{
$arraymerged = [];
if (is_array($array1) && is_array($array2)) {
//collect the keys of two arrays
$keys = [];
foreach ($array1 as $key => $value) {
$keys[$key] = true;
}
foreach ($array2 as $key => $value) {
$keys[$key] = true;
}
//merge key values for each key
foreach ($keys as $key => $value) {
if (isset($array1[$key]) && isset($array2[$key])) {
if ($array1[$key] == $array2[$key]) {
$arraymerged[$key] = $array1[$key];
} else {
$arraymerged[$key] = [$array1[$key], $array2[$key]];
}
} else if (isset($array1[$key]))
$arraymerged[$key] = $array1[$key];
else
$arraymerged[$key] = $array2[$key];
}
return $arraymerged;
}
}
Here is my suggestion,
if the input is array, check my answer on this post Convert an associative array into an associative array which has a key with another associative array as its value in php
otherwise check below code.
bill_number as unique key and run foreach and append items array elements.
let me give you an example
$arr1 = [
"bill_type" => 1,
"bill_number" => 'BIL-003',
"items"=>[
0 => [
"name"=>"test"
]
]
];
$arr2 = [
"bill_type" => 1,
"bill_number" => 'BIL-003',
"items"=>[
0 => [
"name"=>"test_2"
]
]
];
$formattedArr = [];
//merge these arrays
$combinedArr = [];
$combinedArr[] = $arr1;
$combinedArr[] = $arr2;
foreach($combinedArr as $key=>$value){
$formattedArr[$value['bill_number']]["bill_type"] = $value["bill_type"];
$formattedArr[$value['bill_number']]["items"][] = $value["items"];
}
print_r($formattedArr);
I haven't tested this code, but i think this will be ans to your question.
<?php
$a1 = array(
"bill_type" => "1",
"bill_number" => "BIL-003",
"order_number" => "ON-003",
"items" => array(
"track_inventory" => "0",
"sku1" => "sku1",
"name" => "Kidswear1"
)
);
$a2 = array(
"bill_type" => "1",
"bill_number" => "BIL-003",
"order_number" => "ON-003",
"items" => array(
"track_inventory" => "0",
"sku1" => "sku2",
"name" => "Pant"
)
);
$result = function ($a1, $a2) {
$b1 = $a1['items'];
$b2 = $a2['items'];
$c1 = $a1;
$c2 = $a2;
unset($c1['items']);
unset($c2['items']);
if (count(array_diff($c1, $c2)) == 0) {
if (count(array_diff($b1, $b2)) != 0) {
$c1['items'] = [$b1, $b2];
} else {
$c1['items'] = $b1;
}
return $c1;
}else{
//you should complete this part by yourself, if first parts are not equal.
}
return $c1;
};
$r = $result($a1, $a2);
var_dump($r);
result:
(array) [4 elements]
bill_type: (string) "1"
bill_number: (string) "BIL-003"
order_number: (string) "ON-003"
items:
(array) [2 elements]
0:
(array) [3 elements]
track_inventory: (string) "0"
sku1: (string) "sku1"
name: (string) "Kidswear1"
1:
(array) [3 elements]
track_inventory: (string) "0"
sku1: (string) "sku2"
name: (string) "Pant"

How can I get a key value from two arrays on match?

I have 2 arrays, I'm trying to find any matches and return 'url from $array_full.
I tried array_intersect($array_full, $array_ids), but it doesn't work.
$array_full = array
(
Array
(
'#attributes' => Array
(
'topicid' => 102000,
'url' => 'Velkommen.htm',
'alias' => 'Velkommen'
)
),
Array
(
'#attributes' => Array
(
'topicid' => 130313,
'url' => 'WStation/WAS_Indstillinger.htm',
'alias' => 'WAS_Indstillinger'
)
),
Array
(
'#attributes' => Array
(
'topicid' => 130315,
'url' => 'SPedestal/Applikationer/LoadSharing/Indstillinger.htm',
'alias' => 'LOS_Indstillinger'
)
),
Array
(
'#attributes' => Array
(
'topicid' => 130312,
'url' => 'WStation/WAS_Indstillinger.htm',
'alias' => 'WAS_Indstillinger'
)
)
);
$array_ids = array('130312', '130315');
I expect to get an array of matched url's, like:
array('WStation/WAS_Indstillinger.htm','SPedestal/Applikationer/LoadSharing/Indstillinger.htm')
A simple couple of foreach loops seems the easiest approach
$results = [];
foreach ( $array_full as $a ) {
foreach ( $a as $item ) {
if ( in_array($item['topicid'], $array_ids) ) {
$results[] = $item['url'];
}
}
}
print_r($results);
RESULT
Array
(
[0] => SPedestal/Applikationer/LoadSharing/Indstillinger.htm
[1] => WStation/WAS_Indstillinger.htm
)
You will have to make foreach inside foreach to find item that is matching to ID.
Something like this (not tested, may contain some typos).
foreach($array_ids as $id) {
foreach($array_full as $key => $fullItem) {
if($fillItem['#attributes']['topicid'] != $id) {
continue;
}
//do what you need with $fullItem array
$key; // this is the key you want
}
}
you can use array_map, in_array to get the URL's
$result = [];
array_map(function($v) use ($array_ids,&$result){
$result[] = in_array($v['#attributes']['topicid'], $array_ids) ? $v['#attributes']['url'] : '';
}, $array_full);
Result:-
echo '<pre>';
print_r(array_filter($result));
Array
(
[2] => SPedestal/Applikationer/LoadSharing/Indstillinger.htm
[3] => WStation/WAS_Indstillinger.htm
)

Multidimensional array sorting in php [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 6 years ago.
One of my function return this array... Yes I have seen other examples here on SO but non where able to solve my problem.
array (size=4)
0 =>
array (size=2)
'refferrer' => string 'http://google.com/' (length=18)
'number_of_reffers' => string '15' (length=2)
1 =>
array (size=2)
'refferrer' => string 'https://facebook.com/' (length=21)
'number_of_reffers' => string '22' (length=2)
2 =>
array (size=2)
'refferrer' => string 'none' (length=4)
'number_of_reffers' => string '74' (length=2)
3 =>
array (size=2)
'refferrer' => string 'http://findy.com/' (length=17)
'number_of_reffers' => string '6' (length=1)
I will like to know how to sort this array in descending and asscending order using the
'number_of_reffers'...
What I am trying to say is that i want the one with the hishest number_of_reffers to come first, follow by the next and so on.
Is this possible and how can i do this in php.
Thanks for you help.
You need usort
Given your array, you would then do this:
usort( $array, 'sort_by_referrer_count' );
var_dump($array);
// This will sort ascending
function sort_by_referrer_count( $a, $b ) {
// Some defensive coding to ensure keys exist
$a = ( isset( $a['number_of_referrers'] ) ) ? $a['number_of_referrers'] : 0;
$b = ( isset( $b['number_of_referrers'] ) ) ? $b['number_of_referrers'] : 0;
if ($a == $b) {
return 0;
}
return ( $a < $b ) ? -1 : 1;
}
If you want descending, then you could do this (using the same function above):
usort( $array, 'sort_by_referrer_count' );
$array = array_reverse( $array );
In the most simplest sense; you may just want to try this:
<?php
// SORTING ALGORITHM:
// TO SORT IN THE OPPOSITE SENSE...
// (IE. ASCENDING [AS OPPOSED TO THE DEFAULT: DESCENDING]
// CHANGE THE LESS THAN (<) BELOW TO GREATER THAN (>)
function orderByNumRef($arrPrev, $arrNext) {
if ($arrPrev['number_of_reffers'] == $arrNext['number_of_reffers']) {
return 0;
}
return ($arrPrev['number_of_reffers'] < $arrNext['number_of_reffers']) ? -1 : 1;
}
//GIVEN ARRAY - DYNAMIC OR HARD-CODED
$arr = array(
array(
'refferrer' => 'http://google.com/',
'number_of_reffers' =>'15',
),
array(
'refferrer' => 'https://facebook.com/',
'number_of_reffers' =>'74',
),
array(
'refferrer' => 'http://findy.com/',
'number_of_reffers' =>'6',
),
);
//BEFORE SORTING:
var_dump($arr);
uasort($arr, 'orderByNumRef');
//AFTER SORTING:
var_dump($arr);
Hope it helps...
Try this:
<?php
$my_array;
//Sort Acceding
usort($my_array, create_function('$a,$b', 'return (Int)$a["number_of_reffers"]-(Int)$b["number_of_reffers"];'));
//Or sort Descending
usort($my_array, create_function('$a,$b', 'return (Int)$b["number_of_reffers"]-(Int)$a["number_of_reffers"];'));
The easiest way I find to do it is by creating a new array with the number_of_reffers as the key. Then sort the new array with either ksort() or krsort(). This in the end leaves the original array intact. Otherwise creating the original array in the intended format would be better.
<?php
// original array
$array = array(
array('refferrer' => 'http://google.com/', 'number_of_reffers' => '15'),
array('refferrer' => 'https://facebook.com/', 'number_of_reffers' => '22'),
array('refferrer' => 'none', 'number_of_reffers' => '74'),
array('refferrer' => 'http://findy.com/', 'number_of_reffers' => '6')
);
$foo = array(); // new empty array
// loop through $array, assign the number_of_reffers as the key for the refferrer
foreach ($array as $key => $bar) {
$foo[$bar['number_of_reffers']] = $bar['refferrer'];
}
/*
new array will be:
array(
'15' => 'http://google.com/',
'22' => 'https://facebook.com/'
etc .....
)
*/
// use Ksort / Krsort to sort the key asc or desc
ksort($foo); // ascending order
#krsort($foo); // descending order
die('<pre>'.print_r($foo, true).'</pre>'); // pretty printing of sorted array
?>
As a function ....
<?php
Function Referrer_sort($array, $asc = true) {
IF (!is_array($array)) { return 'not an array'; }
$result = array();
foreach ($array as $key => $value) {
$result[$value['number_of_reffers']] = $value['refferrer'];
}
switch ($asc) {
case false: krsort($result); return $result;
default: ksort($result); return $result;
}
}
$foo_asc = Referrer_sort($array);
$foo_desc = Referrer_sort($array, false);
die('<pre>Ascending:<br>'.print_r($foo_asc, true).'<br>Descending:<br>'.print_r($foo_desc, true).'</pre>');
?>
Changing the original array
Modifying the original array by changing the index key with the value of number_of_reffers.
<?php
Function Rebuild_Referrer_sort($array, $asc = true) {
IF (!is_array($array)) { return 'not an array'; }
$result = array();
foreach ($array as $key => $value) {
$result[$value['number_of_reffers']] = array('refferrer' => $value['refferrer'], 'number_of_reffers' => $value['number_of_reffers']);
}
switch ($asc) {
case false: krsort($result); return $result;
default: ksort($result); return $result;
}
}
$foo_asc = Rebuild_Referrer_sort($array);
$foo_desc = Rebuild_Referrer_sort($array, false);
die('<pre>Ascending:<br>'.print_r($foo_asc, true).'<br>Descending:<br>'.print_r($foo_desc, true).'</pre>');
/**
Returns:
Ascending:
Array
(
[6] => Array
(
[refferrer] => http://findy.com/
[number_of_reffers] => 6
)
[15] => Array
(
[refferrer] => http://google.com/
[number_of_reffers] => 15
)
[22] => Array
(
[refferrer] => https://facebook.com/
[number_of_reffers] => 22
)
[74] => Array
(
[refferrer] => none
[number_of_reffers] => 74
)
)
Descending:
Array
(
[74] => Array
(
[refferrer] => none
[number_of_reffers] => 74
)
[22] => Array
(
[refferrer] => https://facebook.com/
[number_of_reffers] => 22
)
[15] => Array
(
[refferrer] => http://google.com/
[number_of_reffers] => 15
)
[6] => Array
(
[refferrer] => http://findy.com/
[number_of_reffers] => 6
)
)
*/
?>

counting occurence on multiple PHP array [duplicate]

This question already has answers here:
Count specific values in multidimensional array
(4 answers)
Closed 9 years ago.
I'm looking for a way to count occurence on an array of array.
This is my array :
Array
(
[0] => Array
(
[id] => 671
[title] => BIEND
[img] =>
[ville] => marseille
)
[1] => Array
(
[id] => 670
[title] => BIENC
[img] =>
[ville] => avignon
)
[2] => Array
(
[id] => 669
[title] => BIENB
[img] =>
[ville] => avignon
)
)
And what I would like to have :
Array
(
[avignon] => 2
[marseille] => 1
)
I tried with array_count_values, but it dont seems to be the good way.
Any idea?
You could just go through it manually:
$result = array();
foreach($input as $item)
{
$result[$item['ville']]++;
}
or, slightly nicer perhaps,
$result = array();
foreach($input as $item)
{
$city = $item['ville'];
if(!array_key_exists($city, $result)) {
$result[$city] = 1;
} else {
$result[$city]++;
}
}
Alternatively, you could do some array_map magic to first get an array with all the cities, and then use array_count_values as you planned:
$cities = array_count_values( array_map( function($a) { return $a['ville']; } ) );
Note, I haven't tested this last solution, I personally think the first one expresses the intention better. If you would like to use this one because it is shorter (i.e. less readable) I'll leave it to you to debug and comment it
You can use array_reduce():
$data = Array
(
0 => Array
(
'id' => 671,
'title' => 'BIEND',
'img' => '',
'ville' => 'marseille'
)
,
1 => Array
(
'id' => 670,
'title' => 'BIENC',
'img' => '',
'ville' => 'avignon'
)
,
2 => Array
(
'id' => 669,
'title' => 'BIENB',
'img' => '',
'ville' => 'avignon'
)
);
$result = array_reduce($data, function(&$cur, $x)
{
$cur[$x['ville']] = isset($cur[$x['ville']])?$cur[$x['ville']]+1:1;
return $cur;
}, []);
$my_array = array(...);
$result = array();
foreach ($my_array as $arr) {
$key = $arr['ville'];
if (! array_key_exists($key, $result){
$result[$key] = 1;
continue;
}
$result[$key] += 1;
}
I would write something like this. Array and subArray should be renamed according to their content.
$villes = array();
foreach($yourArray as $subArray) {
if(!in_array($subArray['ville'], $villes)) {
$villes[$subArray['ville']] = 1;
} else {
$villes[$subArray['ville']]++;
}
}
var_dump($villes);

PHP how to join to records from array

Hi it is any way to connect to records where value is the same?
like
[12]=> Array (
[ID] => 127078
[row1] =>
[post] => N16 7UJ
)
[13]=> Array (
[ID] => 127078
[row1] => something
[post] =>
)
and make like that
[12]=> Array (
[ID] => 127078
[row1] => something
[post] => N16 7UJ
)
Here take this function
<?php
$array = array(
12 => array (
"ID" => '127078',
"row1" => '',
"post" => 'N16 7UJ',
),
13 => array (
"ID" => '127078',
"row1" => 'something',
"post" => '',
)
);
function mergedup($array,$matcher){
if(!function_exists('remove_element')){
function remove_element($arr,$element){
$ret_arr = array();
foreach($arr as $val){
if($val !== $element){
array_push($ret_arr,$val);
}
}
return $ret_arr;
}
}
$array = remove_element($array,array());
$return_array = array();
while(isset($array[0])){
$temp = $array[0];
$array = remove_element($array,$temp);
$array_temp = array();
foreach($array as $vals){
if($temp[$matcher]==$vals[$matcher]){
array_push($array_temp,$vals);
foreach($temp as $key => $val){
if(empty($temp[$key])){
$temp[$key] = $vals[$key];
}
}
}
}
foreach($array_temp as $vals){
$array = remove_element($array,$vals);
}
array_push($return_array,$temp);
}
return $return_array;
}
var_dump(mergedup($array,"ID"));
?>
Tested and working
You have so many option such as array_replace
array_merge
foreach
while
Iterator
But i prefer array_replace because you can easily select which array is replacing which
Values
$array[12] = array("ID"=>127078,"row1"=>"","post"=>"N16 7UJ");
$array[13] = array("ID"=>127078,"row1"=>"something","post"=>"");
var_dump($array[12]);
Example array_replace ( http://www.php.net/manual/en/function.array-replace.php )
$array[13] = array_filter($array[13]); //Filter Replacement
$array[12]= array_replace($array[12],$array[13]);
Example array_merge ( http://php.net/manual/en/function.array-merge.php )
//$array[12] = array_filter($array[12]); //Optinal
$array[13] = array_filter($array[13]); //Filter Spaces
$array[12]= array_merge($array[12],$array[13]);
var_dump($array[12]);
Output
array
'ID' => int 127078
'row1' => string 'something' (length=9)
'post' => string 'N16 7UJ' (length=7)

Categories