Related
I have this code i am using to write json to a file
<?php
require_once 'vendor/autoload.php';
$faker = Faker\Factory::create();
function getAge($start = 18, $end = 100, $repeat = 20){
$result = null;
static $ages = array();
if ( empty($ages) ) {
for ($i= $start; $i <= $end; $i++) {
for($j = 0; $j < $repeat; $j++)
$ages[] = $i;
}
}
$index = rand(0, count($ages));
$result = $ages[ $index ];
unset($ages[ $index ]);
$ages = array_values($ages);
return $result;
}
$superstars = array("Adam Cole","Finn Balor","Pete Dunne","Jordan Devlin","Noam Dar");
$fan_favourite_superstar_name = $superstars[ mt_rand( 0, count($superstars) -1 ) ];
$cities = array("London","Manchester","Leeds","Bristol");
$fan_location = $cities[ mt_rand( 0, count($cities) -1 ) ];
$the_models = array("Iphone","Nokia","Huawei","Samsung");
$fan_phone_model = $the_models[ mt_rand( 0, count($the_models) -1 ) ];
for ($x = 1; $x <= 100; $x++) {
echo $x;
$array = Array (
"$x" => Array (
"id" => uniqid(),
"fan_favourite_superstar_name" => $fan_favourite_superstar_name,
"fan_location" => $fan_location,
"fan_phone_model" => $fan_phone_model,
"fan_name" => $faker->name,
"fan_age" => getAge(),
"fan_comments" => $faker->text,
"fan_picture" => rand(1,500),
"last_updated" => time() + rand(1,1000),
)
);
// encode array to json
$json = json_encode(array('fans' => $array));
//write json to file
if (file_put_contents("data.json", $json))
echo "JSON file created successfully..."."<br/>";
else
echo "Oops! Error creating json file...";
}
?>
When i run, only the first line is written. Why are the other lines not being written?.
You are overwriting the file in each iteration of the loop. You need to tell the file_put_contents function you want to append, like so:
file_put_contents("data.json", $json, FILE_APPEND)
Edit:
Even though this answers the posted question, As Nigel Ren pointed out, this won't create a valid JSON file. Concerning your follow-up comment about the desired format, you'd need to build your array inside the loop and then write once afterwards (by moving everything after $json = json_encode(array('fans' => $array)); outside of the loop).
The correct way to build it is to follow Nigel's first comment about assignment (something the other answers which were deleted in the meantime also dealt with) to avoid overwriting the array each time:
$array["$x"] = Array (
"id" => uniqid(),
...
So, ultimately, you wouldn't even need the appending flag.
I have an array;
$arr=array(1100,3150,4430,4430,5170,7450,7450,7450,8230);
I want to show them in graph. I want my Y-Axis as my elements of that array and X-Axis as sum up the numbers until that element. (x1,x1+x2,x1+x2+x3,...)
My graph will be;
Y-Axis : 1100,3150,4430,4430,5170,7450,7450,7450,8230
X-Axis : 1100,4250,8680,13110,18280,25730,33180,40630,48860
But I have no idea about how to do that. Is there anyone who can help me with it ? Thanks.
My entire code:
<?php
echo " ".'<br>'.'<br>';
$arr=array(1100,3150,4430,4430,5170,7450,7450,7450,8230);
$arrtotal=0;
for($i=0; $i<=8; $i++)
{
if ($arr[$i]<100) {
$arr[$i]=$arr[$i];
}
else
{
$arr[$i]=$arr[$i]/1000;
$arr[$i]=(string)$arr[$i];
}
}
function calculate($arr, $output){
switch($output){
case 'mean':
$count = count($arr)+1;
$sum = array_sum($arr);
$total = $sum / $count;
break;
case 'median':
rsort($arr);
$middle = (count($arr) / 2)+1;
$total = $arr[$middle-1];
break;
case 'mode':
$v = array_count_values($arr);
arsort($v);
foreach($v as $k => $v){$total = $k; break;}
break;
}
return $total;
}
function sd_square($x, $total) { return pow($x - $total,2); }
function sd($arr) {
return sqrt(array_sum(array_map("sd_square", $arr, array_fill(0,count($arr), (array_sum($arr) / count($arr)) ) ) ) / (count($arr)-1) );
}
echo ' '.'<br>';
echo "Values: ";
echo json_encode($arr).'<br>';
echo 'Mean: '.calculate($arr, 'mean').'<br>';
echo 'Median: '.calculate($arr, 'median').'<br>';
echo 'Mode: '.calculate($arr, 'mode').'<br>';
echo "Standart Derivation: ".sd($arr);
?>
<!DOCTYPE HTML>
<html>
<head>
<script>
window.onload = function () {
var data = <?php echo json_encode($arr, JSON_NUMERIC_CHECK); ?>;
data = data.map(function (row, index) {
return {
x: index,
y: row
};
});
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: "Analysis"
},
axisY: {
title: "Variables"
},
data: [{
type: "line",
dataPoints: data
}]
});
chart.render();
}
</script>
</head>
<body>
<div id="chartContainer" style="height: 250px; width: 50%;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</body>
</html>
In this code my X-Axis is (0,1,2,3,4,5,6,7,8) and I don't want that.
I'm sorry if I couldn't explain well, English is not my native language.
The simplest way is just to loop over the values, adding the current array value to the previous output value to create the new output value. You can then convert that into an array of [x => y] values using array_combine:
$arr=array(1100,3150,4430,4430,5170,7450,7450,7450,8230);
$out = array($arr[0]);
for ($i = 1; $i < count($arr); $i++) {
$out[$i] = $out[$i-1] + $arr[$i];
}
$arr = array_combine($out, $arr);
print_r($arr);
Output:
Array (
[1100] => 1100
[4250] => 3150
[8680] => 4430
[13110] => 4430
[18280] => 5170
[25730] => 7450
[33180] => 7450
[40630] => 7450
[48860] => 8230
)
Demo on 3v4l.org
to get that one array into 2 arrays of graph co-ordinates, you can do this:
$x = array();
$y = array();
$running_total = 0;
for($i = 0; $i < count($arr); $i++){
$y[$i] = $arr[$i];
$running_total += $arr[$i];
$x[$i] = $running_total;
}
This will give you two arrays; array $x that contains a list of your X-coordinates, and $y, that gives you a list of your Y-coordinates; and you will still have access to your original $arr array, should you need to do further calculations on it. Based on your question, I think that will get you what you need.
However, if you are saying you want 1 array where the X co-ordinates are the array indexes, and the value is the array value itself, for example $y[3150] = 4250, then that is impossible; because you have duplicates in your original list, you cannot use those values as array indexes without ending up overwriting them.
(At least, not without making each array value an array itself, but that is taking things an order of magnitude above where is probably necessary)
Calculating the running total and storing the data as key-value pairs can be achieved with a foreach() and zero function calls.
Although perhaps a little unorthodox, it is valid syntax to use the "addition assignment" operator as the key of the output array. This updates the $previous value and supplies the calculated value as the key.
Code: (Demo)
$arr = [1100,3150,4430,4430,5170,7450,7450,7450,8230];
$result = [];
$previous = 0;
foreach ($arr as $value) {
$result[$previous += $value] = $value;
}
var_export($result);
// same result as #Nick's answer
Am working on a nested array in PHP (From an API) which is 4 levels deep. Am trying to use a for loop to separate/dissect the nested arrays so that they may exist as independent entities so that I may use them in the blade. e.g agency_sales , unit_sales, agents When I dd on the browser, I get agency_sales while unit_sales I only get one array..
They are stored in a variable called rsm
The array collection
"regional_sales": [
{
"id": "75875",
"agency_sales": [
{
"id": "157",
"unit_sales": [
{
"id": "777",
"agents": [
{
"agent_no": "75939",
"policies": [
"IL*********"
]
},
{
"agent_no": "75939",
"policies": [
"IL**********"
]
}
]
},
{
"id": "111",
"agents": [
{
"agent_no": "758",
"policies": [
"IL2*********"
]
},
{
"agent_no": "75939",
"policies": [
"IL20**********"
]
}
]
}
]
}
]
}
]
My For loop
for($a=0; $a < count($rsm); $a++){
$asm = $rsm[$a]['agency_sales'];
//dd($asm);
for($b = 0; $b < count($asm); $b++){
$usm = $asm[$b]['unit_sales'];
dd($usm);
for($c = 0; $c < count($usm); $c++){
$ag = $usm[$c]['agents'];
//dd($ag);
}
}
}
I think you actually want to collect all the pieces at each level separately and then push down to generate the next level arrays. That will ensure you get all the values at each level into their respective array. This should work:
$asm = array();
for($a=0; $a < count($rsm); $a++){
$asm = array_merge($asm, $rsm[$a]['agency_sales']);
}
print_r($asm);
$usm = array();
for($b = 0; $b < count($asm); $b++){
$usm = array_merge($usm, $asm[$b]['unit_sales']);
}
print_r($usm);
$ag = array();
for($c = 0; $c < count($usm); $c++){
$ag = array_merge($ag, $usm[$c]['agents']);
}
print_r($ag);
I've omitted the output as it is quite long but you can see it on the demo on 3v4l.org
You should use foreach to parse through such an array:
foreach ($data['regional_sales'] as $regional_sale) {
// Access $regional_sale['id'] or anything else
foreach ($regional_sale['agency_sales'] as $agency_sale) {
// Access $agency_sale['id'] or anything else
foreach ($agency_sale['unit_sales'] as $unit_sale) {
// Access $unit_sale['id'] or anything else
foreach ($unit_sale['agents'] as $agent) {
// Access $agent['agent_no'] or anything else
}
}
}
}
Demo: https://3v4l.org/q3dAR
MySQL array
CSV file array
I want to match this two different associative arrays "Url" value. Also I want remaining array value of CSV file i.e. DA, PA, MozRank, Linksln, and so on...
I hope some genius can help me
Thank you
Check this custom PHP script returns you matched url from two array
<?php
/**
* Function for match url and return data
*/
function matchArray($array1, $array2)
{
$index = 0;
$return = array();
$count1 = count($array1);
$count2 = count($array2);
for($i=0; $i < $count1; $i++)
{
for($j=0; $j < $count2; $j++)
{
if($array1[$i]['url'] == $array2[$j]['url']) {
$return[$index]['url'] = $array2[$j]['url']; // Add index which you want to get
$return[$index]['DA'] = $array2[$j]['DA']; // Add index which you want to get
$return[$index]['PA'] = $array2[$j]['PA'];
$return[$index]['MozRank'] = $array2[$j]['MozRank'];
}
$index ++;
}
}
echo "<pre>";
print_r($return); // this will return matched url form two array
}
$array1 = array(array('url' => 'AllConsuming.net' ),array('url' => 'app.brand-mention.com'),array('url' => 'www.microsoft.com'));
$array2 = array(array('url' => 'AllConsuming.net', 'DA' => 48, 'PA'=> 54.4, 'MozRank'=> 5.4),array('url' => 'www.microsoft.com', 'DA' => 31.7, 'PA'=> 54.4, 'MozRank'=> 5.4));
matchArray($array1, $array2); // calling function
?>
If you want to know which entries are indentical, proceed this way :
$array1 = array_column($ar1, 'url'); // return array('AllConsuming.net', 'http://app.brand-mention.com', 'https://www.microsoft.com', 'otherstuff')
$array2 = array_column($ar2, 'url'); // return array('AllConsuming.net', 'TravelIntelligence.net', 'otherstuff')
// compare these 2 arrays
$comp = array_intersect($aray1, $array2);
var_dump($comp); // output array('AllConsuming.net', 'otherstuff');
I have an array of my inventory (ITEMS A & B)
Items A & B are sold as sets of 1 x A & 2 x B.
The items also have various properties which don't affect how they are distributed into sets.
For example:
$inventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK")
);
I want to redistribute the array $inventory to create $set(s) such that
$set[0] => Array
(
[0] => array(A,PINK)
[1] => array(B,RED)
[2] => array(B,BLUE)
)
$set[1] => Array
(
[0] => array(A,MAUVE)
[1] => array(B,YELLOW)
[2] => array(B,GREEN)
)
$set[2] => Array
(
[0] => array(A,ORANGE)
[1] => array(B,BLACK)
[2] => NULL
)
$set[3] => Array
(
[0] => array(A,GREY)
[1] => NULL
[2] => NULL
)
As you can see. The items are redistributed in the order in which they appear in the inventory to create a set of 1 x A & 2 x B. The colour doesn't matter when creating the set. But I need to be able to find out what colour went into which set after the $set array is created. Sets are created until all inventory is exhausted. Where an inventory item doesn't exist to go into a set, a NULL value is inserted.
Thanks in advance!
I've assumed that all A's come before all B's:
$inventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK")
);
for($b_start_index = 0;$b_start_index<count($inventory);$b_start_index++) {
if($inventory[$b_start_index][0] == 'B') {
break;
}
}
$set = array();
for($i=0,$j=$b_start_index;$i!=$b_start_index;$i++,$j+=2) {
isset($inventory[$j])?$temp1=$inventory[$j]:$temp1 = null;
isset($inventory[$j+1])?$temp2=$inventory[$j+1]:$temp2 = null;
$set[] = array( $inventory[$i], $temp1, $temp2);
}
To make it easier to use your array, you should make it something like this
$inv['A'] = array(
'PINK',
'MAUVE',
'ORANGE',
'GREY'
);
$inv['B'] = array(
'RED',
'BLUE',
'YELLOW',
'GREEN',
'BLACK'
);
This way you can loop through them separately.
$createdSets = $setsRecord = $bTemp = array();
$bMarker = 1;
$aIndex = $bIndex = 0;
foreach($inv['A'] as $singles){
$bTemp[] = $singles;
$setsRecord[$singles][] = $aIndex;
for($i=$bIndex; $i < ($bMarker*2); ++$i) {
//echo $bIndex.' - '.($bMarker*2).'<br/>';
if(empty($inv['B'][$i])) {
$bTemp[] = 'null';
} else {
$bTemp[] = $inv['B'][$i];
$setsRecord[$inv['B'][$i]][] = $aIndex;
}
}
$createdSets[] = $bTemp;
$bTemp = array();
++$bMarker;
++$aIndex;
$bIndex = $bIndex + 2;
}
echo '<pre>';
print_r($createdSets);
print_r($setsRecord);
echo '</pre>';
To turn your array into an associative array, something like this can be done
<?php
$inventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK")
);
$inv = array();
foreach($inventory as $item){
$inv[$item[0]][] = $item[1];
}
echo '<pre>';
print_r($inv);
echo '</pre>';
Maybe you can use this function, assuming that:
... $inventory is already sorted (all A come before B)
... $inventory is a numeric array staring at index zero
// $set is the collection to which the generated sets are appended
// $inventory is your inventory, see the assumptions above
// $aCount - the number of A elements in a set
// $bCount - the number of B elements in a set
function makeSets(array &$sets, array $inventory, $aCount, $bCount) {
// extract $aItems from $inventory and shorten $inventory by $aCount
$aItems = array_splice($inventory, 0, $aCount);
$bItems = array();
// iterate over $inventory until a B item is found
foreach($inventory as $index => $item) {
if($item[0] == 'B') {
// extract $bItems from $inventory and shorten $inventory by $bCount
// break out of foreach loop after that
$bItems = array_splice($inventory, $index, $bCount);
break;
}
}
// append $aItems and $bItems to $sets, padd this array with null if
// less then $aCount + $bCount added
$sets[] = array_pad(array_merge($aItems, $bItems), $aCount + $bCount, null);
// if there are still values left in $inventory, call 'makeSets' again
if(count($inventory) > 0) makeSets($sets, $inventory, $aCount, $bCount);
}
$sets = array();
makeSets($sets, $inventory, 1, 2);
print_r($sets);
Since you mentioned that you dont have that much experience with arrays, here are the links to the php documentation for the functions I used in the above code:
array_splice — Remove a portion of the array and replace it with something else
array_merge — Merge one or more arrays
array_pad — Pad array to the specified length with a value
This code sorts inventory without any assumption on inventory ordering. You can specify pattern (in $aPattern), and order is obeyed. It also fills lacking entries with given default value.
<?php
# config
$aInventory=array(
array("A","PINK"),
array("A","MAUVE"),
array("A","ORANGE"),
array("A","GREY"),
array("B","RED"),
array("B","BLUE"),
array("B","YELLOW"),
array("B","GREEN"),
array("B","BLACK"),
array("C","cRED"),
array("C","cBLUE"),
array("C","cYELLOW"),
array("C","cGREEN"),
array("C","cBLACK")
);
$aPattern = array('A','B','A','C');
$mDefault = null;
# preparation
$aCounter = array_count_values($aPattern);
$aCurrentCounter = $aCurrentIndex = array_fill_keys(array_unique($aPattern),0);
$aPositions = array();
$aFill = array();
foreach ($aPattern as $nPosition=>$sElement){
$aPositions[$sElement] = array_keys($aPattern, $sElement);
$aFill[$sElement] = array_fill_keys($aPositions[$sElement], $mDefault);
} // foreach
$nTotalLine = count ($aPattern);
$aResult = array();
# main loop
foreach ($aInventory as $aItem){
$sElement = $aItem[0];
$nNeed = $aCounter[$sElement];
$nHas = $aCurrentCounter[$sElement];
if ($nHas == $nNeed){
$aCurrentIndex[$sElement]++;
$aCurrentCounter[$sElement] = 1;
} else {
$aCurrentCounter[$sElement]++;
} // if
$nCurrentIndex = $aCurrentIndex[$sElement];
if (!isset($aResult[$nCurrentIndex])){
$aResult[$nCurrentIndex] = array();
} // if
$nCurrentPosition = $aPositions[$sElement][$aCurrentCounter[$sElement]-1];
$aResult[$nCurrentIndex][$nCurrentPosition] = $aItem;
} // foreach
foreach ($aResult as &$aLine){
if (count($aLine)<$nTotalLine){
foreach ($aPositions as $sElement=>$aElementPositions){
$nCurrentElements = count(array_keys($aLine,$sElement));
if ($aCounter[$sElement] != $nCurrentElements){
$aLine = $aLine + $aFill[$sElement];
} // if
} // foreach
} // if
ksort($aLine);
# add empty items here
} // foreach
# output
var_dump($aResult);
Generic solution that requires you to specify a pattern of the form
$pattern = array('A','B','B');
The output will be in
$result = array();
The code :
// Convert to associative array
$inv = array();
foreach($inventory as $item)
$inv[$item[0]][] = $item[1];
// Position counters : int -> int
$count = array_fill(0, count($pattern),0);
$out = 0; // Number of counters that are "out" == "too far"
// Progression
while($out < count($count))
{
$elem = array();
// Select and increment corresponding counter
foreach($pattern as $i => $pat)
{
$elem[] = $inv[ $pat ][ $count[$i]++ ];
if($count[$i] == count($inv[$pat]))
$out++;
}
$result[] = $elem;
}