undefined offset in BoxArray - php

I'm trying to calculate the volume of each box but I keep coming across errors and I don't know how to fix it. Everything seem correct and I followed how the book's example.
This is the error it gave me in this code:
"Notice: Undefined offset: 0 in C:\wamp\www\BoxArray.php on line 16"
<?php
$BoxMeasurements = array("sBox" => array("length" => 12, "width" => 10, "depth" => 2.5),
"mBox" => array("length" => 30, "width" => 20, "depth" => 4),
"lBox" => array("length" => 60, "width" => 40, "depth" => 11.5));
$BoxMeasurements = array_slice($BoxMeasurements, 0, 3);
echo "The box sizes are:";
for($i = 0; $i < count($BoxMeasurements); ++$i)
{
echo "$BoxMeasurements[$i]";
}
?>
When I tried doing it the other way I got this error:
"Parse error: syntax error, unexpected '=', expecting ')' in C:\wamp\www\BoxArray.php on line 8"
<?php
$sBox = array("length" => 12, "width" => 10, "depth" = 2.5);
$mBox = array("length" => 30, "width" => 20, "depth" = 4);
$lBox = array("length" => 60, "width" => 40, "depth" => 11.5);
$dimension = array($sBox, $mBox, $lBox);
echo "$dimension[0][0]";
?>
Is there a special way to call the variable/array name?

$BoxMeasurements is declared as an associative array, which means you should access its values with the keys you defined in the declaration: "sBox", "mBox" and "lBox".
In order to iterate over this kind of arrays you can use the foreach form:
<?php
$BoxMeasurements = array("sBox" => array("length" => 12, "width" => 10, "depth" => 2.5),
"mBox" => array("length" => 30, "width" => 20, "depth" => 4),
"lBox" => array("length" => 60, "width" => 40, "depth" => 11.5));
echo "<pre>";
echo "The box sizes are:\n";
foreach($BoxMeasurements as $name => $size)
{
$volume = $size['length'] * $size['width'] * $size['depth'];
echo " - $name: $volume\n";
}
echo "</pre>";
?>
OUTPUT
The box sizes are:
- sBox: 300
- mBox: 2400
- lBox: 27600

You seem not to understand difference between variable name and variable content, as indicated by using " around names. It's pointless. It should be
echo $BoxMeasurements[$i];
While assigning your array, correct syntax is:
key => value
while some of your "rows" are assigned just "key = value" which throws syntax error.
Also you try to access array by numerical indices, while your array does not use them. Use foreach to iterate the array:
foreach( $BoxMeasurements as $key=>$val ) {
echo $val;
}
Finally, you should be doing post increment in your for loop, not pre increment.
I strongly suggest to spend some time and go through some tutorials as you made too many elementary errors.

Related

How to find the closest matching array

Customers of a furniture store website can select products and add them to a "style book". Each product belongs to a "style".
The furniture store has some stylists that each have made their own style book that represents their style and expertise.
I want to be able to find the stylist that best matches a customer's stylebook.
For each style book I have a count of the number of products per style.
$stylists = [
'Nanda' => [
'Design' => 20,
'Retro' => 0,
'Rustiek' => 0,
],
'Angelique' => [
'Design' => 0,
'Retro' => 20,
'Rustiek' => 0,
],
'Lissy' => [
'Design' => 10,
'Retro' => 10,
'Rustiek' => 0,
],
];
The same for the customer's style book:
$customer = [
'Design' => 15,
'Retro' => 10,
'Rustiek' => 0,
];
In this case Lissy should be the best match.
The number of products isn't important since this depends on how active the stylist is.
More important is that the stylist matches most of the customer's styles.
For example:
'Stylist' => [
'Design' => 10,
'Retro' => 10,
'Rustiek' => 0,
]
Should still be a better match than
'Stylist' => [
'Design' => 300,
'Retro' => 0,
'Rustiek' => 180,
]
I have tried giving the stylists' style books scores and percentages based on the order of importance of the customer's style book but still I don't get the best match a 100% of the times.
Google also didn't get me anywhere.
As we have already discussed, the problem with your model is, that it relies on the number of products. But what we need is an indicator of the style the stylist is using. In other words we eliminate the count and replace it with a relatively weighted indicator (percentages in this case). For example a stylist with a product portfolio of:
[
style1 => 30,
style2 => 10,
style3 => 5
]
The product count is 45 = 30 + 10 + 5 this will result in a style-profile like this:
[
style1 => 0.66,
style2 => 0.22,
style3 => 0.11
]
To match the stylist-style-profile with the client-style-profile we need to do the same thing for the client-stylebook [15, 10, 0]:
[
style1 => 0.60
style2 => 0.40
style3 => 0.00
]
The idea behind this is, that we rate how a stylist is influenced by a certain style and the outcome will probably be quite similar for the product that we want to find the best fitting stylist to.
If the stylist made products in a style that is not really what we need for the match, we rate this fact with the weighted relative factor e.g. 0.11. It is not that important, but we still acknowledge the fact that the design might be somewhat biased.
Therefore, if a stylist has a lot of products with a certain style that we are not looking for, it won't change the outcome as much.
Please let me know, if this helps and if you want to change anything. From here we could also implement other options and rules.
Below you find my RatingModel.
<?php
class RatingModel {
private $name;
private $preferences;
private $preferencesWeighted;
public function RatingModel($name, array $preferences) {
$this->name = $name;
$this->preferences = $preferences;
$this->init();
}
private function init() {
$total = 0;
foreach ($this->preferences as $value) {
$total += $value;
}
if ($total > 0) {
foreach ($this->preferences as $value) {
$this->preferencesWeighted[] = $value / $total;
}
} else {
$this->preferencesWeighted = array_fill(0, sizeof($this->preferences), 0);
}
}
public function getName() {
return $this->name;
}
public function getPreferences() {
return $this->preferences;
}
public function getPreferencesWeighted() {
return $this->preferencesWeighted;
}
public function distanceToModel($ratingModel) {
$delta = [];
for ($i = 0; $i < sizeof($this->preferencesWeighted); $i++) {
$delta[] = abs($this->preferencesWeighted[$i] - $ratingModel->getPreferencesWeighted()[$i]);
}
return $delta;
}
public function scoreToModel($ratingModel) {
$distanceToModel = $this->distanceToModel($ratingModel);
$score = [];
foreach ($distanceToModel as $value) {
$score[] = $value * $value;
}
return sqrt(array_sum($score));
}
}
$customer = new RatingModel('Customer', [15, 10, 0]);
$nanda = new RatingModel('Nanda', [20, 0, 0]);
$angelique = new RatingModel('Angelique', [0, 20, 0]);
$lissy = new RatingModel('Lissy', [10, 0, 0]);
$mary = new RatingModel('Mary', [0, 0, 0]);
$max = new RatingModel('Max', [12, 0, 5]);
$simon = new RatingModel('Simon', [17, 2, 5]);
$manuel = new RatingModel('Manuel', [17, 8, 10]);
$betty = new RatingModel('Betty', [16, 9, 5]);
$sally = new RatingModel('Sally', [15, 10, 4]);
$peter = new RatingModel('Peter', [16, 9, 1]);
$stylists = [$nanda, $angelique, $lissy, $mary, $max, $simon, $manuel, $betty, $peter, $sally];
$relativeToClient = [];
foreach ($stylists as $stylist) {
$relativeToClient[] = [
'stylist' => $stylist->getName(),
'distance' => $stylist->distanceToModel($customer),
'score' => $stylist->scoreToModel($customer)
];
}
echo '<pre>';
print_r($stylists);
echo '<hr>';
print_r($customer);
echo '<hr>';
print_r($relativeToClient);
echo '<hr>from best fit to worst (low score means low delta)<hr>';
$results = array_column($relativeToClient, 'score', 'stylist');
asort($results);
print_r($results);
echo '</pre>';
Right below are the results (lower values are better):
Array
(
[Peter] => 0.067936622048676
[Sally] => 0.1700528000819
[Betty] => 0.20548046676563
[Manuel] => 0.35225222874108
[Simon] => 0.3942292057505
[Max] => 0.50765762377392
[Nanda] => 0.56568542494924
[Lissy] => 0.56568542494924
[Mary] => 0.7211102550928
[Angelique] => 0.84852813742386
)
If we look at the two best fitting stylists we notice, that Peter wins over Sally, because Sally has more Products with a different style.
Sally: [15, 10, 4]
Peter: [16, 9, 1]
You may also notice, that Nanda and Lissy have the same score:
Nanda: [20, 0, 0]
Lissy: [10, 0, 0]
// relatively, for both => [1.00, 0.00, 0.00]
They are both regarded equally fitting. Nanda has 5 products more and Lissy has 5 products less of the first style, but it does not matter, because they both only supply one style and this it what matters: How far they are away from the ideal which is the customer-style.
You could also implement the logic so that you have no bias factor and be more strict when it comes to the comparison. In this case you may want to exclude some of the params.
E.g. just comparing [15, 10] and [16, 9] - in this case Sally would actually win, because she has no delta to the customer when it comes to preferences:
Sally:
[
style1 => 0.60,
style2 => 0.40
]
Peter:
[
style1 => 0.64,
style2 => 0.36
]

Why is this array_search returning 0

Consider the following:
$characterStats = [
['strength' => 500],
['dexterity' => 200],
['agility' => 1000],
['intelligence' => 1200],
['health' => 675],
];
$stat = array_search(max($characterStats), $characterStats);
echo $stat;
What I expect: ['intelligence' => 1200]
What I get: 0
Can some one help me out to achieve what I want?
Try the following:
$characterStats = array(
'strength' => 500,
'dexterity' => 200,
'agility' => 1000,
'intelligence' => 1200,
'health' => 675,
);
$stat = array_search(max($characterStats), $characterStats);
echo $stat;
I changed the way the array is declared. I believe you may need to indicate the field name you would like to search if using nested arrays with the following call:
$stat = array_search(max($characterStats), array_column($characterStats, 'KEYNAME'));
However, since each sub array has only 1 element with different "key" it may not be the best approach. For your scenario, you may need to use another approach, where you loop through each element and store the max value found.
With the array as you have it at the moment, the easiest way I can think of doing it as a standard foreach() and keep the maximum value as well as the element where it's found (save doing another search to get the full entry)...
$characterStats = [
['strength' => 500],
['dexterity' => 200],
['agility' => 1000],
['intelligence' => 1200],
['health' => 675],
];
$maxStat = null;
$max = null;
foreach ( $characterStats as $stat ){
if ( current($stat) > $max ) {
$max = current($stat);
$maxStat = $stat;
}
}
print_r( $maxStat);

Getting an error: PHP Fatal error: Unsupported operand types

I just needed a little help from those PHP experts here. I have a little knowledge of PHP. I am getting a PHP Fatal error: Unsupported operand types of this code:
$ticket_item_types += array(
val_paperworkticket => 19,
val_disposal => 9,
comment => 22,
loadtime => 20,
bbls => 23,
disposalticketno => 46,
load_reviewed => 31
);
if keys are variables, then, you have to use $ before variable name, so it must be:
$ticket_item_types += array(
$val_paperworkticket => 19,
$val_disposal => 9,
$comment => 22,
$loadtime => 20,
$bbls => 23,
$disposalticketno => 46,
$load_reviewed => 31
);
if they are strings you have to quote them:
$ticket_item_types += array(
'val_paperworkticket' => 19,
'val_disposal' => 9,
'comment' => 22,
'loadtime' => 20,
'bbls' => 23,
'disposalticketno' => 46,
'load_reviewed' => 31
);
Also, take into account that + operator with arrays must not be understood as sum operator but Union operator
The + operator returns the right-hand array appended to the left-hand array; for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored.
Array Operator (PHP docs)
Your problem comes from your operation +=.
if $ticket_item_types is an array you should use array_push.
Otherwise,
$ticket_item_types = array( val_paperworkticket=>19, val_disposal=>9, comment=>22, loadtime=>20, bbls=>23, disposalticketno=>46, load_reviewed=>31 );
should remove the problem.

Draw a graph from file using PhpMyGraph

In these days i'm trying to draw a graph from a file using PhpMyGraph5.0,
on the autor's site (http://phpmygraph.abisvmm.nl/) there is this example file:
<?php
//Set content-type header
header("Content-type: image/png");
//Include phpMyGraph5.0.php
include_once('phpMyGraph5.0.php');
//Set config directives
$cfg['title'] = 'Example graph';
$cfg['width'] = 500;
$cfg['height'] = 250;
//Set data
$data = array(
'Jan' => 12,
'Feb' => 25,
'Mar' => 0,
'Apr' => 7,
'May' => 80,
'Jun' => 67,
'Jul' => 45,
'Aug' => 66,
'Sep' => 23,
'Oct' => 23,
'Nov' => 78,
'Dec' => 23
);
//Create phpMyGraph instance
$graph = new phpMyGraph();
//Parse
$graph->parseHorizontalLineGraph($data, $cfg);
?>
Because i need to get the input from a file i've modded the example file changing the $data assignment with:
$data = file("$PATH/$MYFILE");
I've formatted the text inside MYFILE and these are some lines of the file:
'00:00' => 19,
'00:05' => 19,
'00:10' => 21,
...
'17:10' => 21,
'17:15' => 21,
'17:20' => 21,
But when i try to draw the graph i obtain this message instead of the graph:
"exception `Exception` with message `The value of the key %s` is not numeric.`"
I've searched in PhpMyGraph5.0.php and i've found the test that throws the exception:
//Loop
foreach($data as $key => $value) {
//Test
if(!is_numeric($value)) {
throw new Exception('The value of the key "%s" is not numeric.');
}
...
I've tried to substitute the "throw Exception" with this cast:
$value=(int)$value;
but i obtain only an empty graph.
If i manually paste the content of MYFILE inside $data = array(PASTE_HERE); it works, but i can't do it manually.
I think that the problem is about the data type of the value, but i've no ideas on how to solve this problem.
Thanks to everyone and sorry for my bad english.
That exception seems to be badly coded, try changing it to this and it should give you the value of the key where it finds the value is not numeric, that may help identify where the error is :-
throw new Exception(sprintf('The value of the key "%s" is not numeric.',$key));
EDIT
Ok I see the problems, you are not getting what you think you are getting from the $data = file("$PATH/$MYFILE");
if you test using this
$data = file("$PATH/$MYFILE");
print_r($data);
You get the output :
Array
(
[0] => '00:00' => 19,
[1] => '00:05' => 19,
[2] => '00:10' => 21,
[3] => '17:10' => 21,
[4] => '17:15' => 21,
[5] => '17:20' => 21
)
So index [0] is actually an array and not a number, hence the error.
You are going to have to rethink the way you input your data.
Try this for size:
Change you data file to look like this
'00:00',19
'00:05',19
'00:10',21
'17:10',21
'17:15',21
'17:20',21
And your code to do this
$data = array();
$handle = fopen('tst.txt', 'r');
while (!feof($handle)) {
$line = fgets($handle, 8192);
list($time,$count) = explode(',',$line);
$data[$time] = $count;
}
fclose($handle);
print_r($data);
This will generate the following array
Array
(
['00:00'] => 19
['00:05'] => 19
['00:10'] => 21
['17:10'] => 21
['17:15'] => 21
['17:20'] => 21
)
Which I assume is what you wanted in the first place.
EDIT 2
Dont change the package, change what you send it
Replace this line
$data[$time] = $count;
With
$data[$time] = (int)$count;
That should do it.

PHP multidimensional array counter

Im trying to make a multidimensional array with two columns. Name and Counter. I can do a single array with all the names. But I dont know how to make it multidimensional and be able to still update the counters. Code i got so far is
if (!in_array($prodname, $da)){
array_push($da, $prodname);
}
and then I can dump it back out with a foreach. How do I make it two dimensional? How can I say alright this exists update the old value? etc.
If you only need name and counter then you should just be able to use a normal array:
$nameCountArray = array();
foreach($names as $name){
if(!array_key_exists($name,$nameCountArray)){
$nameCountArray[$name] = 1;
}else{
$nameCountArray[$name] = $nameCountArray[$name] + 1;
}
}
If you do need multidimensional arrays these are just arrays of arrays and can be accessed as such. A good example of this is using a 2d array to store locations (say on a 3 by 3 grid):
$twoDArray = array(
0 => array(0 => 1,
1 => 4,
2 => 7),
1 => array(0 => 2,
1 => 5,
2 => 8),
2 => array(0 => 3,
1 => 6,
2 => 9)
);
//Grab the item at 1,2
$item = $twoDArray[1][2];//Will give '8'
Supposing you want $da to look like this:
Array(
"name1" => array("score1" => 80, "score2" => 100),
"name2" => array("score1" => 50, "score2" => 60),
"name3" => array("score1" => 90, "score2" => 80),
...
)
Then all you need to do is something like:
function setScore($prodName, $scoreName, $score)
{
global $da;
if (!array_key_exists($prodName, $da)) {
$da[$prodName] = array();
}
$da[$prodName][$scoreName] = $score;
}
setScore("name1", "score1", 80);
setScore("name1", "score2", 100);
setScore("name2", "score1", 50);
...
Unless I'm misunderstanding your question, which is very possible.

Categories