Output to file doesn't look the way it should - php

So I try to send some output to a file but it doesn't look the way I want.
I have a file with some random integer values , it looks like this:
78, 60, 62, 68, 71, 68, 73, 85, 66, 64, 76, 63, 81, 76, 73, 68, 72, 73, 75, 65, 74, 63, 67, 65, 64, 68, 73, 75, 79, 73
4, 6, 9, 11, 16
9, 10, 16, 18, 20
1, 3, 8, 10, 15
Now what I want to do is for each of these lines print the average, max and min number into another file.
My code for this part is:
while (!feof($aFile))
{
$cnt += 1;
$anArray = array();
$anArray = explode(",", fgets($aFile));
foreach ($anArray as $value)
{
$value = (int)$value;
}
$line = "Line $cnt: Average=" . array_sum($anArray) / count($anArray) . " Max=" . max($anArray) . " Min=" . min($anArray);
fwrite($resultsFile, $line);
fwrite($resultsFile, "\n");
}
The problem is that the resultsFile looks like this:
Line 1: Average=70.6 Max= 85 Min= 60
Line 2: Average=9.2 Max= 16
Min=4
Line 3: Average=14.6 Max= 20
Min=9
Line 4: Average=7.4 Max= 15 Min=1
I couldn't exactly copy paste this , because when I do it pastes it the right way
The problem is that it changes line and then prints Min .
Total Average=50.533333333333 Total Max= 85 Total Min=1

This is kinda tricky and is a combination of several moments.
First - you have new line symbol (\n) in each string of your file.
So, for example string 9, 10, 16, 18, 20 is really a 9, 10, 16, 18, 20\n string.
When you explode this string by ,, last element of your $anArray is not 20, but 20\n (with new line).
Now you're trying to cast each element to int, but as by default php works with copy of array, your initial values in $anArray are unchaged. As correctly stated in comments - to apply changes to original array, use $&value notation:
foreach ($anArray as &$value)
{
$value = (int)$value;
}
And last - all following operations on your $anArray silenlty cast 20\n to int (20). But as noticed in max manual, for example:
The actual value returned will be of the original type with no conversion applied
So, in array ['9', '10', '16', '18', '20\n'] max value will be 20, but returned value will be 20\n which creates a new line and moves Min=... output to next line.

Related

Compare the new array with the previous one

I have an array with 4 elements
[1, 2, 3, 4]
So far I am printing several arrays, all with different elements in each array, to a limit set by me.
for($i = 0; $i<=100; $i++){//...
Output so far:
[11, 22, 32, 44]
[22, 33, 44, 45]
[12, 24, 25, 31]
[15, 16, 31, 41]
[22, 33, 44, 45]//already exist
[11, 22, 32, 44]//already exist
...
How can I compare an outgoing array to the next one going out and delete the new one if is equal to the previous array?
You could create a key for an array with the help of implode() and have a set array which has this key. If key is already present, then the current array in iteration is a duplicate one, else it's a new one. Remember to sort the current array as the order of the numbers matter here for proper key check.
<?php
$arr = [
[11, 22, 32, 44],
[22, 33, 44, 45],
[12, 24, 25, 31],
[15, 16, 31, 41],
[22, 33, 44, 45],
[44, 22, 32, 11]
];
$set = [];
foreach($arr as $curr_array){
sort($curr_array);
$hash = implode("|",$curr_array);
if(isset($set[$hash])) echo "Duplicate",PHP_EOL;
else{
print_r($curr_array);
$set[$hash] = true;
}
}
Demo: https://3v4l.org/EXXRu

PHP - Counting array elements in a specific range

I have an array with 950 elements. Values of elements are between 80-110. I want to count how many of them between 80-90, 90-100 and 100-110. Then I'll show them on a graph. Is this possible to count elements like that in php ?
You can simply do it by running a for loop. Create an array containing a range of elements and run a for loop. While you will run the loop on that time count the array element according to your given three groups. Finally you will get the total number of elements inside the given range. For your better help below I am giving an example :
<?php
$number = array(80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110);
$count1 = $count2 = $count3 = 0;
for ($i = 0; $i < sizeof($number); $i++) {
if($number[$i] >= 80 && $number[$i] <= 90 ) {
$count1++;
}
if($number[$i] >= 90 && $number[$i] <= 100 ) {
$count2++;
}
if($number[$i] >= 100 && $number[$i] <= 110 ) {
$count3++;
}
}
echo "The number between 80-90 = ".$count1."<br>";
echo "The number between 90-100 = ".$count2."<br>";
echo "The number between 100-110 = ".$count3."<br>";
?>
I think OP may have been going for a more pythonic answer (but in PHP)
//only valid in php 5.3 or higher
function countInRange($numbers,$lowest,$highest){
//bounds are included, for this example
return count(array_filter($numbers,function($number) use ($lowest,$highest){
return ($lowest<=$number && $number <=$highest);
}));
}
$numbers = [1,1,1,1,2,3,-5,-8,-9,10,11,12];
echo countInRange($numbers,1,3); // echoes 6
echo countInRange($numbers,-7,3); // echoes 7
echo countInRange($numbers,19,20); //echoes 0
the 'use' keyword indicates a 'closure' in php. Taken for granted in other languages, for example javascript, variables in an outer function are imported scope-wise into the inner function automatically (i.e. without special keywords), the inner function may also be called a "partial function".
For some reason in PHP 5.2x or lower, variables were not imported scope-wise automatically, and in PHP 5.3 or higher, the use keyword can overcome this. The syntax is very simple:
$functionHandle = function(<arguments>) use (<scope-imported variables>){
//...your code here...
}
To avoid having too many comparisons jump to next loop when you have determined where your number belongs.
function countOccurences( array $numbersArray ):array
{
$return = array('n80to90' => 0, 'n90to100' => 0, 'n100to110' => 0);
foreach( $numbersArray as $number ){
if( $number < 80 || $number > 110 )
continue;
if($number < 91){
$return['n80to90']++;
continue;
}
if($number < 101){
$return['n90to100']++;
continue;
}
$return['n100to110']++;
}
return $return;
}
I cannot imagine that your statistical graphic that would want to represent values on the cusp of two groups as belonging to both groups. For this reason, I'll offer a condition-less function-less technique which can be execute in a foreach loop.
Code: (Demo)
$sampleData = range(80, 110);
$result = array_fill_keys(['80s', '90s', '100s'], 0); // set 0 defaults for incrementation
foreach ($sampleData as $value) {
++$result[(10 * ((int)($value / 10) <=> 9) + 90) . 's'];
}
var_export($result);
Output:
array (
'80s' => 10,
'90s' => 10,
'100s' => 11,
)
My technique manufactures the appropriate keys from the values by:
Dividing by 10
Truncating the decimal (same effect as floor()
Making a 3-way comparison via the spaceship operator (returns -1, 0, or 1)
Multiplying the "-1|0|1" by 10
Adding 90
And finally concatenating an "s".
The ++ means add 1 to the current value of the element with the corresponding key.
Alternatively, if you wanted to group the values as "90+below" (80-90), "100+below" (91-100), and "110+below" (101-110), then it is a simple matter of adjusting the key-generating factors.
Instead of counting, I'll show the elements assigned to each group.
Code: (Demo)
$sampleData = range(80, 110);
foreach ($sampleData as $value) {
$result[(10 * ((int)(($value - 1) / 10) <=> 9) + 100) . '+under'][] = $value;
}
var_export($result);
Output:
array (
'90+under' =>
array (
0 => 80,
1 => 81,
2 => 82,
3 => 83,
4 => 84,
5 => 85,
6 => 86,
7 => 87,
8 => 88,
9 => 89,
10 => 90,
),
'100+under' =>
array (
0 => 91,
1 => 92,
2 => 93,
3 => 94,
4 => 95,
5 => 96,
6 => 97,
7 => 98,
8 => 99,
9 => 100,
),
'110+under' =>
array (
0 => 101,
1 => 102,
2 => 103,
3 => 104,
4 => 105,
5 => 106,
6 => 107,
7 => 108,
8 => 109,
9 => 110,
),
)

Generate random numbers from given character set. PHP

How to generate a random from the following list of numbers-
a) 1 to 50 (one from the list)
b) 6, 12, 18, 24, 30 (one from the list)
c) 7, 13, 19, 25, 31 (one from the list)
d) 3 to 75 (one from the list)
Try following that will help you
$fixarray1 = array(6, 12, 18, 24, 30);
$fixarray2 = array(7, 13, 19, 25, 31);
$arra1 = rand(1, 50);
$arra2 = array_rand($fixarray1,1);
$arra3 = array_rand($fixarray2,1);
$arra4 = rand(3, 75);
echo $arra1."-".$arra2."-".$arra3."-".$arra4;

sort multidimensional array by values in PHP

I have an array fetched from mysql database tables of type. I want to sort it in order of particular value.
$arr1=array(array(12, 8, 5, 34),
array(54, 87, 32, 10),
array(23, 76, 98, 13),
array(53, 16, 24, 19));
How can i sort it by value?
Like sorting by 2nd value should result to.
$arr1=array(array(12, 8, 5, 34),
array(53, 16, 24, 19),
array(23, 76, 98, 13),
array(54, 87, 32, 10));
I like to use usort to solve these problems.
$sortKey = 1;
usort($arr1, function($a, $b) use($sortKey){
return $a[$sortKey] - $b[$sortKey];
});
Got to agree with #RocketHazmat, array_multsort is a royal pain in the backside. usort is much easier to follow but I thought I'd have a go anyway:
$sortKey = 1;
array_multisort(array_map(function($v) use($sortKey){
return $v[$sortKey];
}, $arr1), $arr1);
It only took 20 minutes... :(
Here's a demo: http://ideone.com/2rZYIz

Sending multidimensional array from jQuery to php

I am passing an array from jQuery to php.
The array is generated from a table with this code:
var stitchChartArray = [];
var row = 0;
// turn stitch chart into array for php
$('#stitchChart').find('tr').each(function (index, obj) {
//first row is table head- "Block #"
if(index != 0){
stitchChartArray.push([]);
var TDs = $(this).children();
$.each(TDs, function (i, o) {
var cellData = [$(this).css('background-color'), $(this).find("img").attr('src')];
stitchChartArray[row].push(cellData);
});
row++;
}
});
In console it looks like this:
[[["rgb(75, 90, 60)", "symbols/177.png"], ["rgb(75, 75, 60)", "symbols/184.png"], ["rgb(75, 90, 60)", "symbols/177.png"], 7 more...], [["rgb(105, 105, 105)", "symbols/163.png"], ["rgb(75, 75, 60)", "symbols/184.png"], ["rgb(75, 90, 60)", "symbols/177.png"], 7 more...], [["rgb(105, 105, 105)", "symbols/163.png"], ["rgb(75, 90, 60)", "symbols/177.png"], ["rgb(75, 75, 60)", "symbols/184.png"], 7 more...], [["rgb(75, 90, 60)", "symbols/177.png"], ["rgb(75, 90, 60)", "symbols/177.png"], ["rgb(98, 119, 57)", "symbols/210.png"], 7 more...], [["rgb(105, 105, 105)", "symbols/163.png"], ["rgb(105, 105, 105)", "symbols/163.png"], ["rgb(150, 150, 195)", "symbols/72.png"], 7 more...], [["rgb(75, 165, 105)", "symbols/187.png"], ["rgb(134, 158, 134)", "symbols/64.png"], ["rgb(165, 180, 180)", "symbols/171.png"], 7 more...], [["rgb(60, 150, 75)", "symbols/189.png"], ["rgb(120, 120, 90)", "symbols/225.png"], ["rgb(143, 163, 89)", "symbols/209.png"], 7 more...]]
It represents each row of a table->each cell of row->[0]rgb value of bg of cell [1]icon in cell.
This jQuery code returns the correct element(and rgb value) from the array:
alert(stitchChartArray[1][1][0]); //row 1,cell 1, first value(rgb)
But when it gets sent to the php script with this:
$.post('makeChartPackage.php', {'stitchChart[]': stitchChartArray }, function(data){
alert(data);
});
The php throws an error:
Cannot use string offset as an array in /Users/tnt/Sites/cross_stitch/makeChartPackage.php on line 33
$stitchChart = $_POST['stitchChart'];
echo $stitchChart[1][1][0]; //line 33
I am assuming I am either constructing the array incorrectly or passing it to the php script incorrectly.
EDIT:
I did this to return the array to jQuery:
$stitchChart = $_POST['stitchChart'];
print_r($stitchChart);
And here was the result:
Array
(
[0] => rgb(75, 90, 60),symbols/177.png,rgb(75, 75, 60),symbols/184.png,rgb(75, 90, 60),symbols/177.png,rgb(98, 119, 57),symbols/210.png,rgb(180, 195, 105),symbols/388.png,rgb(165, 165, 120),symbols/235.png,rgb(75, 75, 60),symbols/184.png,rgb(90, 90, 45),symbols/195.png,rgb(120, 120, 75),symbols/156.png,rgb(105, 105, 105),symbols/163.png
[1] => rgb(105, 105, 105),symbols/163.png,rgb(75, 75, 60),symbols/184.png,rgb(75, 90, 60),symbols/177.png,rgb(75, 90, 60),symbols/177.png,rgb(165, 165, 120),symbols/235.png,rgb(120, 120, 75),symbols/156.png,rgb(75, 90, 60),symbols/177.png,rgb(75, 90, 60),symbols/177.png,rgb(105, 105, 105),symbols/163.png,rgb(120, 120, 90),symbols/225.png
[2] => rgb(105, 105, 105),symbols/163.png,rgb(75, 90, 60),symbols/177.png,rgb(75, 75, 60),symbols/184.png,rgb(75, 90, 60),symbols/177.png,rgb(98, 119, 57),symbols/210.png,rgb(75, 90, 60),symbols/177.png,rgb(75, 75, 60),symbols/184.png,rgb(105, 105, 105),symbols/163.png,rgb(120, 120, 90),symbols/225.png,rgb(105, 105, 105),symbols/163.png
It appears the array is not multidimensional?
$_POST['stitchChart'] in the context you have addressed it there is (effectively) a JSON representation of a multidimensional array, stored as a string. When you treat a string as a multidimensional indexed array in PHP, you will get that error. The first [x] is treated as a "string offset" - i.e. the character at position x - but the next and any subsequent [x] addresses can only be treated as arrays (you cannot get a substring of a single character) and will emit the error you have received.
To access your data as an array in PHP, you need to use json_decode():
$stitchChart = json_decode($_POST['stitchChart'],TRUE);
echo $stitchChart[1][1][0];
EDIT
Because the jQuery data argument seemingly can't deal with multidimensional arrays, you should use Douglas Crockford's JSON-js library and pass the result into data as a string. NB: use json2.js.
Here is how you could do this:
stitchChartArray = JSON.stringify(stitchChartArray);
$.post('makeChartPackage.php', {'stitchChart': stitchChartArray }, function(data){
alert(data);
});
If you use this code, my original PHP suggestion should work as expected.

Categories