PHP: How will array depth influence performance? - php

Now I know there is some related questions on this topic but this is somewhat unique.
I have two array structures :
array(
[0] => array(
'stat1' => 50,
'stat2' => 12,
'stat3' => 0,
'country_name' => 'United States'
),
[1] => array(
'stat1' => 40,
'stat2' => 38,
'stat3' => 15,
'country_name' => 'Ireland'
),
[2] => array(
'stat1' => 108,
'stat2' => 0,
'stat3' => 122,
'country_name' => 'Autralia'
)
)
and the second
array(
'stat1' => array(
'countries' => array(
'United States' => 50,
'Ireland' => 40,
'Autralia' => 108,
)
)
),
'stat2' => array(
'countries' => array(
'United States' => 12,
'Ireland' => 38,
)
)
),
etc...
The second array can go even to level 4 or 5 if you add the cities of those respective countries. Further to note is that the second array structure will have no 0 data fields (note that in the second one australia is not there because it is 0) but the first structure will have a whole whack of zeros. Also note that the second structure will have duplicates i.e. 'United States'
My question is this: How does these array structures compare when they are json_encode() and used in a POST ajax request? Will the shallow depth array, with it's whack of zeros be faster or will the better structured array be better in terms of size?

I have done some testing and for a finite dataset the difference in the output data - (I outputted the data into a text file) between the two is insignificant really.
Array structure 1 - All city and country data outputs to 68kb
Array structure 2 - All city and country data outputs to 71kb
So there is a slight difference but it seems that the difference is insignificantly small when taking into account that the data is in JSON format and used in an AJAX request to the google visualization geomap API.
I haven't tested the micro times in loading difference but for a user to look at a loading .gif image for 0.0024microseconds (i'm shooting a random time for the sake of argument) does not make a big dent in usability either way. Thanx all for you comments

Related

PHP All possible combinations from a x deep array

I have an array:
array(
'ten' => array(
0, => array('four', 'five', 'six'),
1, => array('seventy', 'fourty', 'thirty')
),
'twenty' => array(
0, => array('four', 'five', 'six'),
1, => array('seventy', 'fourty', 'thirty')
),
'thirty' => array(
0, => array('four', 'five', 'six'),
1, => array('seventy', 'fourty', 'thirty')
)
)
i would like to be able to come up with all unique 'leveled' combinations, so in this example i would end up with the following combinations
ten,four,seventy
ten,four,fourty
ten,four,thirty
ten,five,seventy
ten,five,fourty
ten,five,thirty
ten,six,seventy
ten,six,fourty
ten,six,thirty
enz. for the twenty and thirty "first keys".
i have tried to write some recursive loop, using for loops, while loops, and combined, but cant really figure it out, what i know is that there will always be a first level keyd "first number", so that will always be the first number in any combination, then the sublevels will be the same for each "First number", but the amount of children, and the amount of it's children are dynamic...

Parsing information from PHP Object

I need some help trying to parse informaiton ti display in a form. Right now when using the basic array an address is returned as "3 Columbus PlaceApt1" where Address 1 and Address 2 are returned joined together. I created an object that returns this with print_r
a:2:{
s:18:"_gravity_form_lead";a:16:{
s:4:"19.1";s:28:"Stamford PD Extra Duty Order";s:4:"19.2";s:5:"$0.00";s:4:"19.3";s:0:"";s:3:"9.1";s:16:"3 Columbus Place";s:3:"9.2";s:5:"Apt 1";s:3:"9.3";s:0:"";s:3:"9.4";s:11:"Connecticut";s:3:"9.5";s:0:"";s:3:"9.6";s:13:"United States";i:22;s:14:"(203) 123-4567";i:12;s:10:"2016-05-24";i:13;s:8:"12:35 am";i:20;s:8:"8|584.64";i:11;s:9:"MH6151684";i:21;s:1:"3";i:18;s:7:"1753.92";}s:18:"_gravity_form_data";a:15:{s:2:"id";s:1:"6";s:13:"display_title";b:0;s:19:"display_description";b:0;s:25:"disable_woocommerce_price";s:3:"yes";s:12:"price_before";s:0:"";s:11:"price_after";s:0:"";s:20:"disable_calculations";s:2:"no";s:22:"disable_label_subtotal";s:3:"yes";s:21:"disable_label_options";s:3:"yes";s:19:"disable_label_total";s:2:"no";s:14:"disable_anchor";s:2:"no";s:14:"label_subtotal";s:8:"Subtotal";s:13:"label_options";s:7:"Options";s:11:"label_total";s:5:"Total";s:8:"use_ajax";s:2:"no";
}
}
I want to parse our s:16 and s:5 but im not sure how to do it. Any help is appreciated
EDIT
Unserialized string:
array ( '_gravity_form_lead' => array ( '19.1' => 'Stamford PD Extra Duty Order', '19.2' => '$0.00', '19.3' => '', '9.1' => '3 Columbus Place', '9.2' => 'Apt 1', '9.3' => '', '9.4' => 'Connecticut', '9.5' => '', '9.6' => 'United States', 22 => '(203) 123-4567', 12 => '2016-05-24', 13 => '12:35 am', 20 => '8|584.64', 11 => 'MH6151684', 21 => '3', 18 => '1753.92', ), '_gravity_form_data' => array ( 'id' => '6', 'display_title' => false, 'display_description' => false, 'disable_woocommerce_price' => 'yes', 'price_before' => '', 'price_after' => '', 'disable_calculations' => 'no', 'disable_label_subtotal' => 'yes', 'disable_label_options' => 'yes', 'disable_label_total' => 'no', 'disable_anchor' => 'no', 'label_subtotal' => 'Subtotal', 'label_options' => 'Options', 'label_total' => 'Total', 'use_ajax' => 'no', ), )
You're doing this the hard way!
This is WordPress. You don't need to get a record, unserialize it, try and guess at the structure, etc.
Instead, use the get_option or get_postmeta functions to get the information you want.
Further, there's documentation for both WooCommerce and Gravity Forms that will explain how to get the information you're looking for - BUT, this is a bit of an XY Problem - you've asked how to parse an array (Serialized) - but REALLY you are trying to do something else. You should ask THAT question, rather than the details of this question.
If you must do this manually, do not use unserialize. Instead, use the WordPress function maybe_unserialize
Lastly, the way Gravity Forms stores records is a major nuisance. It's very difficult to map the way it is stored to the "form field" that you set up in the form - unless you use the Gravity Forms API, which makes it somewhat better.
You have to unserialize the array to get the data you need. Like this:
$formData = unserialize($var);
// This is Address1
echo $formData['_gravity_form_lead']['9.1'];
echo "<br/>";
// This is Address2
echo $formData['_gravity_form_lead']['9.2'];

MongoDB find query with $and $or and $nearSphere in php

After quite some trying out and web research I go crazy with this query. I want to build a query for 'Clubs' around a geo point (distance max 500 meters) in php on MongoDB.
But when I run query it ignores the distance limit and shows all clubs in database BUT sorted by distance.
Here is my dataset (2dsphere index geoLoc):
{"_id":ObjectId("547c649e30afe32c23000048"),"name":"Club Ritzz","category":"Club","category_list":[{"id":"191478144212980","name":"Night Club"}],"location":{"city":"Mannheim"},"geoLoc":{"type":"Point","coordinates":[8.473665839156,49.484065272756]}}
{"_id":ObjectId("547c649f30afe32c2300004a"),"name":"Das Zimmer Mannheim","category":"Club","category_list":[{"id":"191478144212980","name":"Night Club"}],"geoLoc":{"type":"Point","coordinates":[8.4709362941178,49.487260552592]}}
{"_id":ObjectId("547c64ab30afe32c23000063"),"name":"Nationaltheater Mannheim","category":"Arts/entertainment/nightlife","category_list":[{"id":"173883042668223","name":"Theatre"}],"geoLoc":{"type":"Point","coordinates":[8.4776534992592,49.48782606969]}}
{"_id":ObjectId("547c64a130afe32c2300004f"),"name":"SOHO Bar Club Lounge","category":"Club","category_list":[{"id":"191478144212980","name":"Night Club"},{"id":"164049010316507","name":"Gastropub"}],"geoLoc":{"type":"Point","coordinates":[8.4630844501277,49.49385193591]}}
{"_id":ObjectId("547c64a730afe32c2300005a"),"name":"Loft Club","category":"Club","category_list":[{"id":"191478144212980","name":"Night Club"},{"id":"176139629103647","name":"Dance Club"}],"geoLoc":{"type":"Point","coordinates":[8.4296300196465,49.484211928258]}}
And here my php code (updated Dec-2):
$qry = $pub->find(
array( '$and' =>
array(
array( 'geoLoc' =>
array('$nearSphere' =>
array('$geometry' =>
array('type'=>'Point',
'coordinates'=>
array(
floatval($sLon), floatval($sLat)
)
),
'maxDistance' => 500
)
)
),
array( '$or' =>
array(
array( 'name' => new MongoRegex("/.*club/i")),
array( 'name' => new MongoRegex("/.*zimm/i"))
)
),
array('$or' =>
array(
array('category_list.name' => 'Night Club'),
array('category_list.name' => 'Dance Club'),
array('category' => 'Club')
)
)
)
),
array('id' => 1, 'name' => 1, '_id' => 0)
);
Anyone know why the results are not limited to the specified maxDistance?
I found a similar issue on StackOverflow which outlines that one has to use radians for the maxDistance parameter.
See https://dba.stackexchange.com/questions/23869/nearsphere-returns-too-many-data-what-am-i-missing-am-i-wrong-is-it-a-bug-d
Also it is probably helpful if you'd test the query in mongo shell without using the PHP APIs first (just to see if the query is generally working and append '.explain()' to it to see what generally happens inside DB).

Multi-sorting a complex array in PHP

I have a relatively complex array in PHP that needs to be sorted in a specific way but the number of filters and sorts is a bit on the complex side that a simple solution seems to be escaping me.
The Problem: We have products in an order that need to be filtered into "shipto" groups based on the following criteria: Date the product can be shipped, if the product can be grouped with other products, and in which warehouse(s) the product can be shipped from. If 2 products have the same date, warehouse, and allow grouping then they are placed together in the same "shipto".
Current Solution (Not fully realized)
When I extract an order I traverse the items in it and build an array with the following information (FYI, this probably contains more info than I need to solve this problem)
$allProducts = array();
$today = date("Ymd");
/* If the product is being shipped now, put in the Today ShipTo dated 00000000 */
if (($today > $start) && ($today < $end)) {
array_push($allProducts, array('ship' => '00000000', 'defaultwarehouse' => $defaultwarehouse, 'warehouse' => $warehouse, 'group' => $group,'product' => $product, 'start_month' => $start_month, 'start_day' => $start_day, 'end_month' => $end_month, 'end_day' => $end_day, 'description' => $description, 'qty_ordered' => $qty_ordered, 'row_total' => $row_total, 'price' => $price, 'tax_amount' => $tax_amount, 'shipping_group' => $shippingGroup, 'today' => $today, 'end' => $end, 'start' => $start ) );
} else {
/* If the product is not being shipped today, put in a Group that matches the starts date for the ShipTo */
array_push($allProducts, array('ship' => $start, 'defaultwarehouse' => $defaultwarehouse, 'warehouse' => $warehouse, 'group' => $group, 'product' => $product, 'start_month' => $start_month, 'start_day' => $start_day, 'end_month' => $end_month, 'end_day' => $end_day, 'description' => $description, 'qty_ordered' => $qty_ordered, 'row_total' => $row_total, 'price' => $price, 'tax_amount' => $tax_amount, 'shipping_group' => $shippingGroup, 'today' => $today, 'end' => $end, 'start' => $start ));
}
endif;
Where $defaultwarehouse is a number representing the default warehouse (i.e. 1), $warehouse is all of the possible warehouses a product can be in (i.e. 1,2), $start is the date a product can first be shipped (i.e. 20121201 for Dec 1, 2012; Ymd, 00000000 represents today so they can be numerically sorted) and $group is a boolean saying if the product can or can not be shipped with other items (i.e. 1 for yes, 0 for no)
My original idea here was to sort the array based on group, then on warehouse, then on start date. I would then traverse the array to build the "shipto"s and when certain components of the array change (like Warehouse or Start) I would close the previous shipto and start a new one. If I take Group and Multiple Warehouses out of the equation I can get this logic to work. But my task requires I have them in so I am running into the following complications.
First, after I sort by Group, I really want to do 2 sub-sorts of Group=Yes and Group=No for the rest of the filters. This lead me to think that maybe I should be separating the array into 2 arrays and sorting them similarly but separately. It seems inefficient to do it this way but I am not sure.
Second, since warehouse can be a comma separated value, how can I filter on that and get the proper matches. i.e. if I have 3 products where their warehouse value is 1:1,2:3 this should group into 2 shiptos. One for 1:1,2 and a Second for 3.
Thoughts on the problem
My feeling is the way I am thinking about this problem with filtering the items into a traversable array may not be the best way to tackle it. It may be that I need to push the order items individually into a new "Shipments" array that checks each item against all current "Shipments". But I am also not exactly sure on how that would work. Or there may be a different way I am not thinking about at all about how to achieve this.
Example Array Data (Extra Data removed for simplicity):
[0]=>
'ship' => 00000000
'defaultwarehouse' => 1
'warehouse' => 1
'group' => 1
'sku' => 'ABC123'
[1]=>
'ship' => 00000000
'defaultwarehouse' => 1
'warehouse' => 1,2
'group' => 1
'sku' => 'DEF234'
[2]=>
'ship' => 00000000
'defaultwarehouse' => 2
'warehouse' => 1,2
'group' => 1
'sku' => 'GHI567'
[3]=>
'ship' => 20121220
'defaultwarehouse' => 1
'warehouse' => 1,2
'group' => 1
'sku' => 'JKL890'
[4]=>
'ship' => 20121220
'defaultwarehouse' => 1
'warehouse' => 1,2
'group' => 1
'sku' => 'MNO123'
[5]=>
'ship' => 20130401
'defaultwarehouse' => 1
'warehouse' => 1
'group' => 1
'sku' => 'PQR456'
[6]=>
'ship' => 20130401
'defaultwarehouse' => 1
'warehouse' => 1
'group' => 0
'sku' => 'STU789'
This should result in 5 "shipto" groups:
shipto[1] => ABC123, DEF234 (Base "group" for all other comparisons)
shipto[2] => GHI567 (Default warehouse does not match, previous shiptos)
shipto[3] => JKL890, MNO123 (Different shipping date)
shipto[4] => PRQ456 (Different shipping date from all others)
shipto[5] => STU789 (Can not be grouped with other shipments)
Is it possible for you to store the data in a database or somewhere similar? It sounds like your data is pretty complex, and storing it in a database would make the sorting you're looking to do a lot easier.
In the end this problem got even more complex and I generally threw away the concept of being able to sort logically and applying sub-sorts to a single array or SQL query. The business logic changed so much that keeping this all straight made no sense in one dimension.
The final logic applies 4 levels of filtering so what I did was isolate each step of logic and filter the previous array into a new array with the orders in their proper place. It is NOT the most efficient way to handle this but it is very readable and allows me to clearly see how each order is getting sorted at each step of the process. The "sorted" array is 4 levels deep but allows me to cherry pick each shipment for proper display.

mongodb - search in subarray, PHP

i started with mongodb and played around with random temperature data
like this:
'weather' => array(
'Air' => array(
'Jan' => 11,
'Feb' => 20,
'Mar' => 24,
'Jun' => 28,
'Jul' => 30
)
),
Now my question:
How can i query the Air array ?
I knwo i can do somethin like:
$query = array('weather.Air.Jan' => 11);
Works fine...
But how can i search in the whole Air array:
$query = array('weather.Air.$' => 40);
This query doesn't work...
Can somebody help me
Unfortunately, the query you're looking for does not exist.
As written, you're asking for "weather.Air where a key in the JSON object contains a value of 40".
MongoDB has the ability to "drill into" arrays. However, when it comes to sub-objects, you have to reach into the keys directly. There is no operator that provides a "search all keys" method. There is an outstanding JIRA request for this item right here.

Categories