For example, I have inserted 10K documents in collection:
for ($i = 0; $i < 100; ++$i) {
for ($j = 0; $j < 100; ++$j) {
$collection->insert(array('i' => $i, 'j' => $j));
}
}
I have created Indexes:
pkrs:PRIMARY> db.testTest.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "parts.testTest",
"name" : "_id_"
},
{
"v" : 1,
"key" : {
"i" : 1,
"j" : 1
},
"ns" : "parts.testTest",
"name" : "i_1_j_1"
}
]
Then I want to fetch 600 documents with 'OR' condition:
for ($i = 5; $i < 12; ++$i) {
for ($j = 0; $j < 100; ++$j) {
$orArr[] = array('i'=>$i, 'j' => $j);
}
}
$cursor = $collection->find(array('$or' => $orArr));
$cursor->batchSize(1000);
foreach ($cursor as $doc) {
// code
}
And first document fetches about 1.5 second! :(
How can I improve performance?
Related
I have two arrays:
$colors = [ 'gold', 'silver', 'bronze', 'wood' ];
$emotion = [ 'happy', 'sad', 'wow', 'angry' ];
Out of those, I can make up 16 elements, so that colors and emotion don't repeat. I can easily generate all the unique elements by nesting 2 foreach loops.
$items = array();
foreach ( $colors as $c ) {
foreach( $emotion as $e ) {
$items[] = array( $c => $e );
}
}
The problem is that I need to create a 4x4 grid out of those 16 elements so that every column and every row contains only 1 element with particular color AND emotion.
To further explain, one row, of 4 elements( from the $items array ), can only contain one element of each emotion and color. It can not have colors nor emotions repeat in a row. The same goes for column.
What would be the proper way to do it? I'm pretty sure I need some condition checks and recursion, but not sure how to do it.
EDIT: Add example output
As for the output, it should be an array of four arrays, 4 elements in each, like so:
array(4) {
[0]=>
array(4) {
["bronze"]=>
string(5) "angry"
["gold"]=>
string(3) "happy"
["silver"]=>
string(3) "sad"
["wood"]=>
string(5) "wow"
}
[1]=>
array(4) {
["gold"]=>
string(5) "happy"
["bronze"]=>
string(3) "wow"
["wood"]=>
string(5) "angry"
["silver"]=>
string(3) "sad"
}
[2]=>
array(4) {
["silver"]=>
string(5) "happy"
["wood"]=>
string(3) "sad"
["bronze"]=>
string(5) "angry"
["gold"]=>
string(3) "wow"
}
[3]=>
array(4) {
["wood"]=>
string(5) "happy"
["silver"]=>
string(3) "wow"
["gold"]=>
string(5) "angry"
["bronze"]=>
string(3) "sad"
}
}
Here's a( one of ) solution:
bronze->angry | gold->happy | silver->sad | wood->wow
gold->sad | bronze->wow | wood->angry | silver->happy
silver->wow | wood->sad | bronze->happy | gold->angry
wood->happy | silver->angry | gold->wow | bronze->sad
Ok, so you need to first collect all possible pairs as you did.
Now, we will try to place a pair at a location if no collision in the grid and check with other pairs.
If the current placement fails, we try another location and so on and so forth.
(Scroll to the end to check with a working demo if you would like to see this in action first)
generateGrid:
<?php
function generateGrid($colors, $emotions, &$grid){
$combs = [];
foreach($colors as $color){
foreach($emotions as $emotion){
$combs[] = [$color, $emotion];
}
}
/* initialize grid */
for($i = 0; $i < count($colors); ++$i){
for($j = 0; $j < count($emotions); ++$j){
$grid[ $i ][ $j ] = [];
}
}
/* initializing grid ends */
if(makeGrid($combs, $grid, 0, count($colors) * count($emotions))){
return true;
}
$grid = [];// restore the grid to original state
return false;
}
makeGrid:
<?php
function makeGrid($combs, &$grid, $idx, $total){
if($idx == $total) return true;
for($i = 0; $i < count($grid); ++$i){
for($j = 0; $j < count($grid[ $i ]); ++$j){
if(count($grid[ $i ][ $j ]) == 0){
if(noCollision($combs[ $idx ], $i, $j, $grid)){
$grid[ $i ][ $j ] = $combs[ $idx ];
if(makeGrid($combs, $grid, $idx + 1, $total)){
return true;
}
$grid[ $i ][ $j ] = [];
}
}
}
}
return false;
}
noCollision check method:
<?php
function noCollision($element, $row, $col, $grid){
$rowSet = [];
for($i = 0; $i < count($grid[ $row ]); ++$i){
if(count( $grid[ $row ][ $i ]) > 0){
$rowSet[$grid[ $row ][ $i ][ 0 ]] = true;
$rowSet[$grid[ $row ][ $i ][ 1 ]] = true;
}
}
if(isset($rowSet[ $element[0] ]) || isset($rowSet[ $element[1] ])){
return false;
}
$colSet = [];
for($i = 0; $i < count($grid); ++$i){
if(count( $grid[ $i ][ $col ]) > 0){
$colSet[$grid[ $i ][ $col ][ 0 ]] = true;
$colSet[$grid[ $i ][ $col ][ 1 ]] = true;
}
}
return !(isset($colSet[ $element[0] ]) || isset($colSet[ $element[1] ]));
}
Driver code:
<?php
$grid = [];
if(generateGrid([ 'gold', 'silver', 'bronze', 'wood' ], [ 'happy', 'sad', 'wow', 'angry'], $grid)){
printGrid($grid);
}else{
throw new \Exception("No solution found!!");// or whatever you would like to have here
}
Online Demo
Code Demo to print all combinations
We can design an algorithm but your exercise is to write it in PHP. grid(y,x) takes columns y and rows x that holds y in place and "rotates" x one-by-one -
gold/smile
silver/sad
bronze/wow
wood/angry
gold/sad
silver/wow
bronze/angry
wood/smile
gold/wow
silver/angry
bronze/smile
wood/sad
gold/angry
silver/smile
bronze/sad
wood/wow
Immutable rotate(a,i) of some array a and index i takes elements up to the index and puts them on the end of the array.
We'll show the implementation in JS because it's easy to demonstrate in the browser and verify the result -
const grid = (y, x) =>
y.length > x.length // Note below
? grid(x, y)
: x.map((_, i) => Object.fromEntries(zip(y, rotate(x, i))))
const zip = (a, b) =>
a.length && b.length
? [[a[0], b[0]], ...zip(a.slice(1), b.slice(1))]
: []
const rotate = (a, i) =>
a.length < 2
? a
: [ ...a.slice(i), ...a.slice(0, i) ]
const colors = [ 'gold', 'silver', 'bronze', 'wood' ]
const emotions = [ 'smile', 'sad', 'wow', 'angry' ]
console.log(JSON.stringify(grid(colors, emotions)))
console.table(grid(colors,emotions))
Object.fromEntries is the JS equivalent of (object) [ "key" => "value", ... ] in PHP.
Open your console to view the console.table output -
Note, for non-square grids, x must be the longer array, otherwise grid(y,x) will calculate grid(x,y). Can you reason why this is the case?
Here is my code. I'm trying to scrape a table.
$page = file_get_contents('https://www.jncb.com/Support/Help-Resources/Foreign-Exchange-Services');
$dom = new DOMDocument();
$html = $page;
$data = array();
$fx = array();
$cnt = 0;
libxml_use_internal_errors(true);
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$my_xpath_query = "//table//tbody[contains(#class, 'FxRContainer')]//td";
$result_rows = $xpath->query($my_xpath_query);
foreach ($result_rows as $key=>$result_object) {
$data[] = $result_object->nodeValue;
}
for ($i=0; $i < 28; ++$i) {
if( $i % 2 == 0 ) {
$fx[] = $data[$i];
}
}
for ($i=0; $i < 14; ++$i) {
if ( $i % 2 == 0 ) {
$fx[$i] = substr($fx[$i], 6);
}
}
print_r($fx);
echo json_encode($fx, JSON_PRETTY_PRINT);
Here are my results:
[
"USD",
"120.00",
"GBP",
"171.20",
"CAD",
"95.50",
"EUR",
"148.30",
"KYD",
"0.00",
"TTD",
"0.00",
"JPY",
"1.11"
]
You're very close.
In order to create JSON from PHP you need an associative array. Right now you have a standard array.
For example:
$associative_array = [
'currency' => 'USD',
'amount' => 120.00
];
OR
$associative_array = [
'USD' => 120.00
];
The exact example for your case:
foreach($result_rows as $key => $result_object) {
// took a guess here
// not entirely sure if you want the $key or the $result_object->nodeValue to be substr'd
$data[$key] = substr($result_object->nodeValue, 6);
}
Then you can use json_encode() to encode it to a JSON object:
$json = json_encode($associative_array);
I'm trying to repeat N times an array with a FOR loop, but I've been stuck in the last array that contains more elements. This is my code so far:
function data() {
for ($i = 1 ; $i <= 50 ; $i++) {
$magnitud = array('nombre' => 'medidor');
for ($j = 1 ; $j <= 5 ; $j++) {
$magnitude['magnitude'.$i] = array('date' => $date, 'value' => mt_rand(1,200));;
}
}
return $magnitude;
}
for ($i = 1 ; $i <= 50 ; $i++) {
$center->insertOne(['meter' => 'meter'.$i, 'data' => data()]);
}
I need to repeat 5 times the values of the array that contains the date and a value.
array('date' => $date, 'value' => mt_rand(1,200));
Something like this:
Date: 05/03/2015
Value: 25
Date: 10/12/2012
Value: 45
Date: 15/06/2005
Value: 67
Date: 26/05/2009
Value: 78
.
.
.
I've tried it in many ways, but I haven't acieved. Someone who lend me a hand to how to repeat N times that array?
Just in case you haven't got any idea about my question, I attach this picture wich is what I get in Robo3T (Visual Manager)
EDIT: To explain myself better, this is the json that I'm trying to get.
"_id" : ObjectId("5ab0c29db57dce17e0002bc0"),
"meter" : "meter1",
"data" : {
"magnitude1" : {
"date" : "20/10/2015 21:57:05",
"value" : 192,
"date" : "13/12/2015 22:51:15",
"value" : 85,
"date" : "15/05/2016 05:21:06",
"value" : 65,
"date" : "28/06/2017 15:32:26",
"value" : 72,
"date" : "02/11/2017 18:15:34",
"value" : 12,
},
"magnitude2" : {
"date" : "15/12/2009 15:21:32",
"value" : 45,
"date" : "12/05/2013 16:45:07",
"value" : 96,
"date" : "21/02/2015 03:06:12",
"value" : 85,
"date" : "15/08/2015 14:05:22",
"value" : 78,
"date" : "05/01/2017 21:12:32",
"value" : 198,
},
.
.
.
}
I think you mean you want to have 5 sub arrays of the magnitude array, so do it like this
function data() {
for ($i = 1 ; $i <= 50 ; $i++) {
for ($j = 1 ; $j <= 5 ; $j++) {
$magnitude['magnitude'.$i][] = array('date' => $date, 'value' => mt_rand(1,200));;
}
}
return $magnitude;
}
Not the use of [] in this line $magnitude['magnitude'.$i][] which will create a new sub occurrence within $magnitude['magnitude'.$i] each time round the inner loop
It is happening because the values are always overwrited as the key is never changed in the second loop. You can simplify it like this:
function data()
{
$value = 0;
for ($i = 0; $i < 250 ; $i++) {
$value = $i % 5 === 0 ? mt_rand(1, 200) : $value;
$magnitude['magnitude' . ($i + 1)] = array('date' => $date, 'value' => $value);
}
return $magnitude;
}
I need a proper JSON file with "geo_langitude", "geo_latitude", "adress" & "url" values
I have wp database with post_meta "property" - "geo_langitude" "geo_latitude" & "address" in there.
my file is smth like that
<?php
function return_markers($count) {
$query = new WP_Query('post_type=property&posts_per_page=-1&orderby=menu_order&order=DESC&post_status=publish');
$array = array();
$i = 0;
for ($i = 0; $i< $count; $i++) {
$elem = array(
't' => 'string '.$i,
'x' => get_post_meta($post->ID,'geo_latitude',true),
'y' => get_post_meta($post->ID,'geo_longitude',true),
'z' => $i
);
$array[] = $elem;
}
echo json_encode($elem);
};
return_markers($i);
?>
It's my first time using JSON so I have troubles and I don't know where. =(
with random markers work perfectly:
<?php
function return_markers($count) {
$array = array ();
for ($i = 0; $i< $count; $i++) {
$elem = array(
't' => 'string '.$i,
'x' => 23 + (rand ( 0 , 10000 ) / 10000) * 5,
'y' => 56.2 + (rand ( 0 , 10000 ) / 10000) * 0.8,
'url' => '#map_redirect_'.$i,
'z' => $i
);
$array[] = $elem;
}
echo json_encode($array);
};
return_markers(23);
?>
I want to create an array in a for-loop so i can adjust the size ($i) of the array.
I've tried this:
$array = array();
for($i = 1; $i <= 5; $i++) {
array_push($array,
$i => array(
"id" => "",
"option" => ""
)
);
}
But I get the following error:
Parse error: syntax error, unexpected '=>' (T_DOUBLE_ARROW) in ...
I'v also tried to make it a string by doing $i."" on line 4 but that doesn't seem to work either. Does anyone know why?
More idiomatic would be:
$array = array();
for($i = 1; $i <= 5; $i++) {
$array[$i] = array(
"id" => "",
"option" => "") ;
}
However note that this will give you array indexes from 1-5. Arrays are usually indexed from 0:
$array = array();
for($i = 0; $i < 5; $i++) {
$array[$i] = array(
"id" => "",
"option" => "") ;
}
But this can be done without specifying the key:
$array = array();
for($i = 1; $i <= 5; $i++) {
$array[] = array(
"id" => "",
"option" => "") ;
}
try this:
$array = array();
for($i = 1; $i <= 5; $i++) {
$array[$i] = array(
"id" => "",
"option" => ""
);
}
Remove the $i =>
$array = array();
for($i = 1; $i <= 5; $i++) {
array_push($array, array(
"id" => "",
"option" => ""
)
);
}