MongoCollection group question - php

<?php
$collection->insert(array("category" => "fruit", "name" => "apple"));
$collection->insert(array("category" => "fruit", "name" => "peach"));
$collection->insert(array("category" => "fruit", "name" => "banana"));
$collection->insert(array("category" => "veggie", "name" => "corn"));
$collection->insert(array("category" => "veggie", "name" => "broccoli"));
$keys = array("category" => 1);
$initial = array("items" => array());
$reduce = "function (obj, prev) { prev.items.push(obj.name); }";
$g = $collection->group($keys, $initial, $reduce);
echo json_encode($g['retval']);
?>
not clear line $keys = array("category" => 1); why need write "category" => 1 instead of symply write "category" ?

why need write "category" => 1 instead of symply write "category" ?
The query engine for MongoDB used JSON objects. So everything is a key-value pair. The PHP driver is representing key-value pairs using hash tables (or dictionaries).
If you look at the aggregation documentation, it has the following example:
key: { a:true, b:true }
In PHP this would be represented as
$key: array('a' => 1, 'b' => 1)
I agree that the 1 seems unnecessary, but it's there to keep the JSON syntax valid.

Related

Dynamic create parent-child relationship array based on another table field values

There are 2 arrays Say
1. Groups
$groups = array("user", "account", "client")
2. Results
$results = array(
0 => array(
"user" => "U1",
"account" => "A1",
"client" => "C1"
),
1 => array(
"user" => "U1",
"account" => "A2",
"client" => "C1"
),
0 => array(
"user" => "U1",
"account" => "A3",
"client" => "C1"
),
0 => array(
"user" => "U1",
"account" => "A2",
"client" => "C2"
),
0 => array(
"user" => "U1",
"account" => "A1",
"client" => "C4"
),
0 => array(
"user" => "U1",
"account" => "A1",
"client" => "C5"
),
0 => array(
"user" => "U1",
"account" => "A2",
"client" => "C5"
)
) ;
I want following OUTPUT
$output = array(
"U1" => array(
"A1" => array(C1,C4,C5),
"A2" => array(C1,C2,C5),
"A3" => array(C1)
)
);
The Groups array values are dynamic and may be any order. I want output in order the first value of groups array is the parent element of Output array and second value of group array is the child of parent Output array and so on.
I hope you are using PHP greater or equal to 5.6. There we have ... (splat operator) that will come really handy:
$output = [];
array_map(function (...$keys) use (&$output) {
// Pop the last key, because it is actually a value.
$value = array_pop($keys);
// Prepare "element" to assign the value to using keys and references.
$element = &$output;
while($key = array_shift($keys)) {
if (!isset($element[$key])) {
$element[$key] = [];
}
$element = &$element[$key];
}
$element[] = $value;
}, ...array_map(function ($group) use ($results) {
return array_column($results, $group);
}, $groups));
Here is working demo.
In short, we take advantage of the ability of array_map to take any number of arrays as arguments and traverse them kinda parallelly.
Simply make a foreach loop like this
$new = array();
foreach($results as $key=>$value){
$new[$value["user"]][$value["account"]][] = $value["client"];
}
print_r($new);
live demo : https://eval.in/857969
Using $groups : https://eval.in/857970
$new = array();
foreach($results as $key=>$value){
$new[$value[$groups[0]]][$value[$groups[1]]][] = $value[$groups[2]];
}
Example for multiple user's : https://eval.in/857973
Update
For dynamic groups array : You can use eval if you are not interacting user input here. : https://eval.in/858306

PHP multidimensional array search key by value

For example a multidimensional array like an example below
$arr = array(
[H1] => array(
"name" => "A"
"title" => "T1"
)
[H2] => array(
"name" => "B"
"title" => "B1"
)
)
Let's say I would like to search name which equals to A in $arr and if it's matched, the searching should return the key which is H1
How can I do that in php ?
I tried array_keys($arr, "A") but it returns me with an array instead of the key.
This may help -
$arr = array(
'H1' => array(
"name" => "A",
"title" => "T1",
),
'H2' => array(
"name" => "B",
"title" => "B1",
)
);
// Generate a new array with 'keys' and values in 'name'
$new = array_combine(array_keys($arr), array_column($arr, 'name'));
// Search in that new array
$search = array_search('A', $new);
var_dump($search);
Output
string(2) "H1"
Demo
Another simple way would be -
$serach= false;
foreach($arr as $key => $val) {
if($val['name'] == 'A') {
$search= $key;
break;
}
}
var_dump($search);

Sorting Multi-Dimensional Array PHP

I've that proceed this array in PHP
array(
"id" => 1,
"name" => "Carlos"
"other" => array("key" => "Hello")
),
array(
"id" => 3,
"name" => "Carlos"
"other" => array("key" => "Hello")
),
array(
"id" => 2,
"name" => "Carlos"
"other" => array("key" => "Hello")
)
and I need to order by "id". I've try it using usort and many multidimensional solutions but doesn't work for me.
I used that:
$price = array();
foreach ($inventory as $key => $row)
{
$price[$key] = $row['price'];
}
array_multisort($price, SORT_DESC, $inventory);
But doesn't work because my array has many dimentions.
$departamento = $this->Departamentos->get($id, [
'contain' => [
'Asignaturas.Mallas',
'Asignaturas.Secciones.Perfiles',
'Asignaturas.Secciones.Mallas.Carreras',
'Unidades'
]
]);
That is my query in Cakephp. I need to order by Secciones.id
I used Hash::sort
http://book.cakephp.org/3.0/en/core-libraries/hash.html
And works fine for me ;)

PHP array_udiff weird behavior

I have 2 arrays, $array0 and $array1. Let's pre-fill them:
$user01 = array("no" => 1, "name" => "john");
$user02 = array("no" => 2, "name" => "lewis");
$user03 = array("no" => 3, "name" => "dan");
$array0 = array($user01, $user02, $user03, $user04);
$user11 = array("id" => 1, "name" => "john", "attr" => "foo");
$user12 = array("id" => 7, "name" => "mark", "attr" => "bar");
$array1 = array($user11, $user12);
I want to get all users from $array0 who are not in $array1, so I use array_udiff:
$diff = array_udiff($array0, $array1, function ($userA, $userB) {
return $userA['no'] == $userB['id'];
});
However, inside the anonymous compare function, if I do a var_dump of $userA and $userB, they both seem to belong to $array0, while the behavior I was expecting is for $userA to belong to $array0 and $userB to $array1.
I.e., the expected answer is [[2, "lewis"], [3, "dan"]], but I get a 'not found index': "Undefined index id" in the line of the comparison function.
Am I missing something on array_udiff behavior?
I'm pretty sure PHP expects the arguments to the comparison function to be interchangeable, you either need to change the array indexes to be common, or implement logic in the comparison function to deal with this.
That's not how a comparison function works.
The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
So:
$user01 = array("id" => 1, "name" => "john"); // "no" changed to "id"
$user02 = array("id" => 2, "name" => "lewis");
$user03 = array("id" => 3, "name" => "dan");
$array0 = array($user01, $user02, $user03); // non-existant $user04 removed
$user11 = array("id" => 1, "name" => "john", "attr" => "foo");
$user12 = array("id" => 7, "name" => "mark", "attr" => "bar");
$array1 = array($user11, $user12);
$diff = array_udiff($array0, $array1, function ($userA, $userB) {
if( $userA['id'] == $userB['id'] ) { return 0; } // compare function re-jiggered
else { return $userA['id'] - $userB['id']; }
});
print_r($diff);
Yields:
Array
(
[1] => Array
(
[id] => 2
[name] => lewis
)
[2] => Array
(
[id] => 3
[name] => dan
)
)

How to get a specific data from array?

Right now I have a problem with retrieving data form arrays, maybe it's really simple (probably it is) but I am struggling wiht it since morning and it appears, that my knowledge about PHP is worth nothing...so I have few arrays:
array( "name" => "Array 1",
"type" => "array"),
array( "name" => "Array 2",
"type" => "whatever"),
array( "name" => "Array 3",
"type" => "whatever"),
array( "name" => "Array 4",
"type" => "array"),
array( "name" => "Array 5",
"type" => "whatever"),
What I need to do is to display 'name' of arrays of the 'array' type, I know I need a foreach loop but how to construct 'foreach ($arrays as $array) {' to get the desired result?
EDIT
Thanks for all the replies, but I tihnk I didn't make myself clear. I need to display "name" only when there is a "type" => "array" present within array, every other arrays' "name" should be omitted.
You'll need to do something like this:
foreach($arrays as $array) {
if($array['type'] == 'array') {
print($array['name']);
}
}
An array_map will do
array_map(function ($v){ if($v['type']=="array"){echo $v['name']."<br>";}},$arr);
OUTPUT :
Array 1
Array 4
Demo
put the arrays into a "container" array first, then you can use that one...
<?php
$data = array(
array( "name" => "Array 1",
"type" => "array"),
array( "name" => "Array 2",
"type" => "whatever"),
array( "name" => "Array 3",
"type" => "whatever"),
array( "name" => "Array 4",
"type" => "array"),
array( "name" => "Array 5",
"type" => "whatever")
);
foreach($data as $array) {
if($array['type'] == 'array') {
print($array['name']);
}
}

Categories