I want to import my table data into multi-dimensional array in PHP, the table data is continuously updating, so the matrix has to be updated as soon as data is inserted in the table.
How do we create a multi-dimensional array, insert data into it and then append the data dynamically into the array?
Usually, you got a "normal" one-dimensional array out of your table.
To make a multidimensional-array out of it, you have to put the one-dimensional array into a multidimensional array.
To do this, you could use something like:
$i = 0; //initialize i
while ($i < count($array)) { //as long as i is smaller than the array
foreach ($array as $key => $value) { //walk along the array
$newArray[$i][$key] = $value; // set the multidimensional array
}
$i++; // count one up
}
With this, you should get a multidimensional array looking like:
array(
'0' => array(
'0' => 'foo'
'1' => 'bar'
)
'1' => array(
'0' => 'foo'
'1' => 'bar'
)
)
and so on... hope this helps
For what you want to do i think should should look at objects approach because form the following comments
Tom, the scenario is i am maintaining a table for term frequency in the documents, so my column1 will be the different terms in all the documents, and a new column is added for every new document and is inserted with the respective term count, and if it has any new term;
I can identify the following
Team
Document
Rather than make document null only update the required team information
Example
// Porpulate Teams
$teams = array_map(function ($v) {return new Team($v);}, range("A", "Z"));
// Porpulate Documents
$doc = new SplObjectStorage();
for($i = 0; $i < 100; $i ++) {
$doc->attach(new Document($teams[array_rand($teams)]));
}
usort($teams, function($a,$b){ return $b->frequency - $a->frequency;});
//Top 10 Teams
echo "<pre>";
foreach (array_slice($teams, 0,10) as $team ) {
echo "Team ", $team->name, "\t", $team->frequency, PHP_EOL;
}
Output
Team P 9
Team N 8
Team S 7
Team Q 6
Team M 6
Team D 6
Team O 5
Team G 5
Team K 5
Team F 5
Class Used
class Document {
function __construct(Team &$team) {
//Do your metrix
$team->frequency ++;
}
}
class Team {
public $name;
public $frequency = 0;
function __construct($name) {
$this->name = $name;
}
}
Related
Let's say I have an array of items with each item a value. I'd like to
create a new array where the items are clustered by their relative distance to each other.
When an item has a distance of one to another item, they belong to each other.
$input = [
'item-a' => 1,
'item-b' => 2,
'item-c' => 3,
'item-d' => 5,
];
$output = [
['item-a', 'item-b'],
['item-b', 'item-c'],
['item-d'],
];
This will create an output of overlapping arrays. What I want is that, because item-a and item-b are related, and item-b is also
related to item-c, I'd like to group item-a, item-b, and item-c to each other. The distance to item-c and item-d is greater than
1 so it will for a cluster of itself.
$output = [
['item-a', 'item-b', 'item-c'],
['item-d'],
];
How do I even start coding this?
Thanks in advance and have a nice day!
This can only be tested in your environment but here is what it does
it attempts to find relative distances based on array index 0's hash
it resorts the input array by distances (assuming that in this stage some will be positive and some negative) - that gives us the info to put the hash array in an order
Take this new array and put the hash back in
build a final output array measuring distances and sorting the level of output array by a threshhold.
I put in a couple dummy functions to return distances, obviously replace with your own. This might need tweaking but at this point, it's in your hands.
<?php
// example code
$input = [
'item-a' => 'a234234d',
'item-f' => 'h234234e',
'item-h' => 'e234234f',
'item-b' => 'f234234g',
'item-m' => 'd234234j',
'item-d' => 'm234234s',
'item-e' => 'n234234d',
'item-r' => 's234234g',
'item-g' => 'f234234f',
];
function getDistanceFrom($from, $to) {
return rand(-3,3);
}
function getDistanceFrom2($from, $to) {
return rand(0,7);
}
// first sort by relative distance from the first one
$tmp = [];
$ctr = 0;
foreach ($input as $item => $hash) {
if ($ctr === 0) { $ctr ++; continue; }
$tmp[$item]=getDistanceFrom(reset($input), $hash);
}
uasort($tmp, function ($a, $b)
{
return ($a < $b) ? -1 : 1;
});
//now they're in order, ditch the relative distance and put the hash back in
$sortedinput = [];
foreach ($tmp as $item => $d) {
$sortedinput[$item] = $input[$item];
}
$output=[];
$last=0;
$level=0;
$thresh = 3; // if item is within 3 of the previous, group
foreach($sortedinput as $v=>$i) {
$distance = getDistanceFrom2($last, $i);
if (abs($distance) > $thresh) $level++;
$output[$level][]=array("item" => $v, "distance" => $distance, "hash" => $i);
$last = $i;
}
print_r($output);
This question already has answers here:
Working out averages using two dimensional arrays in PHP
(3 answers)
Closed last month.
I am working with 4 arrays, each array contains students last names and their test grades for 4 different tests. What I am trying to do is find the average For each student, calculate and display their average grade. How would I find Smiths average grade from all 4 arrays? I am very new to PHP so any directions would be useful. Thank you!
PHP:
$testOne = array (
'Smith'=> 98,
'Johnson' => 67,
);
$testTwo = array (
'Smith'=> 100,
'Johnson' => 85,
);
$testThree = array (
'Smith'=> 78,
'Johnson' => 92,
);
$testFour = array (
'Smith'=> 91,
'Johnson' => 88,
);
I found one way to get the average but can anyone tell me if there is a more efficient way? I created separate arrays for each student and then divided by the count.
$smith = array(98,100,91,75);
$johnson = array(67,88,85,81)
echo('Smiths average test score is ' . array_sum($smith) / 4);
$TestResult = [
'Smith' => ['98', '100', '78', '91'],
'Johnson' => ['67', '85', '92', '88']
];
$Total = array_sum($TestResult['Smith']); // We are getting the array sum.
$Average = $Total/count($TestResult['Smith']); // the average is being calculated.
echo $Average;
https://3v4l.org/U3gCA
You can do this way.
Reference :
manual count
source count
manual array_sum
source array_sum - source
Suppose students have given four tests(as you said above) namely $testOne, $testTwo and $testThree and $testFour, then create an array like this,
$array = array('One', 'Two', 'Three', 'Four');
Declare a variable to capture total score,
$totalScore = 0;
Declare a student's name whose average score you want to calculate,
$candidate = 'Smith';
Use a foreach loop sum the candidate's total score of all subjects,
foreach($array as $a){
$totalScore += ${'test'.$a}[$candidate];
}
Finally, calculate that candidate's average score like this,
$averageScore = $totalScore / count($array);
Here's the complete code:
$array = array('One', 'Two', 'Three', 'Four');
$totalScore = 0;
$candidate = 'Smith';
foreach($array as $a){
$totalScore += ${'test'.$a}[$candidate];
}
$averageScore = $totalScore / count($array);
echo $averageScore;
Reference links:
foreach loop
Assignment operator
Variable variables
String operators
if php 7+
$test[]['Smith'] = 98;
$test[]['Johnson'] = 67;
$test[]['Smith'] = 100;
$test[]['Johnson'] = 85;
$test[]['Smith'] = 78;
$test[]['Johnson'] = 92;
$test[]['Smith'] = 91;
$test[]['Johnson'] = 88;
then you can do the math
$avarage['Smith'] = array_sum(array_column($test, 'Smith'))/count($test);
$avarage['Johnson'] = array_sum(array_column($test, 'Johnson'))/count($test);
or even make a function
function avarage($name, $test)
{
return array_sum(array_column($test, $name))/count($test);
}
calling function:
$avarage['Smith'] = avarage('Smith', $test);
$avarage['Johnson'] = avarage('Johnson', $test);
You can build a total array of all the arrays and loop one of them to get the student names.
Use the name in array_column to get the values from all the students scores and calculate the average.
Add the values to an associative array for convince.
$total = [$testOne, $testTwo, $testThree, $testFour];
foreach($total[0] as $name => $val){
$averages[$name] = array_sum(array_column($total, $name))/count($total);
}
var_dump($averages);
Returns:
array(2) {
["Smith"]=>
float(91.75)
["Johnson"]=>
int(83)
}
If there had been more students this method would catch them all and just append the array.
https://3v4l.org/Lk1aL
I'm probably just overlooking the obvious but I'd like to blame it on the fact that I'm new to PHP.
I have some number of arrays being returned with similar information but differing amounts of it.
I'll put some example arrays below:
(t1-s1-1=1, t1-s1-2=1, t1-s2-1=1, t1-s2-2=1)
(t2-s1-1=1, t2-s2-1=2, t2-s2-2=1)
(t3-s1-1=1, t3-s2-1=1, t3-s3-1=1, t3-s3-2=3)
So I would like to make a table out of this information. Something like this:
test .. s1-1 .. s1-2 .. s2-1 .. s2-2 .. s3-1 .. s3-2
t1 ........1 .....1 ..........1 ....... 1.........1..........1
t2 ........1 .......X..........1..........1........1..........1
t3 ........1 .......X..........1..........X........1..........1
( where x is something that wasn't there. )
So every array has an s1 but could have s1-1, s1-2, s1-3 or simply s1-1. That creates very different sized arrays.
The problem is that each array can have wildly different information and because they are Indexed arrays instead of Associative arrays I'm not sure how to best equalize them. I can't consistently say index 3 is s1-3 or something else.
I can't just loop through manually because I never know where a gap will appear. I can't look for specific indexes because the arrays aren't associative so the titles are built into the value and I don't know how to access them separately.
Any good ideas out there that maybe a newbie is overlooking? I'm open to non-tabular display ideas as well as long as I can easily sort and display the information.
Thanks
I'm assuming your original arrays contain values as string, so for instance, in PHP syntax, they look like:
['t1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1', 't1-s2-2=1']
Basically, you should create a bi-dimensional array:
go through all arrays and by using a regex extract the different parts, that is, for the first element in the array above: t1 (the index for the first level in the bi-dimensional array), s1-1 (the index for the second level in the bi-dimensional array) and the value 1
insert the value in the bi-dimensional array
keep in a separate array, let's call it allColumns every second index above (sx-y), even you will have duplicate values you can, at the end, delete those duplicate and order it alphabetically
After that, you will have all the value in the bi-dimensional array but you still miss the gaps, so what you can do it iterate over the bi-dimensional array, and for every dimension tz (t1, t2,...), go through for all the values stored in allColumns and if you don't find the entry for that sx-y in the bi-dimensional array for that tz, add it with value x (or probably with value = 0)
I think an example can clarify the above:
// arrays of arrays, I don't know how you receive the data
$arrays = [
['t1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1', 't1-s2-2=1'],
['t2-s1-1=1', 't2-s2-1=2', 't2-s2-2=1'],
['t3-s1-1=1', 't3-s2-1=1', 't3-s3-1=1', 't3-s3-2=3']
];
// bi-dimensional array
$output = [];
// it will store all columns you find in the $arrays entry
$allColumns = [];
// iterate for every array you receive, i.e. ['t1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1', 't1-s2-2=1']
foreach ($arrays as $array) {
// iterate over every element in the array: 't1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1' and 't1-s2-2=1'
foreach ($array as $item) {
// extract the parts on every element: $matches is an array containing the different parts
preg_match('/^(t\d+)-(s\d+-\d+)=(\d+)/', $item, $matches);
/**
* $matches[0] would contains the element if matched: 't1-s1-1=1'
* $matches[1] would contains 't1' if matched
* $matches[2] would contains 's1-1' if matched
* $matches[2] would contains 1 (integer) if matched
*/
if (!empty($matches)) {
$output[$matches[1]][$matches[2]] = $matches[3];
$allColumns[] = $matches[2];
}
}
}
// clean duplicates
$allColumns = array_unique($allColumns);
// sort values alphabetically
sort($allColumns);
// iterate over the just created bi-dimensional array
foreach ($output as $row => $columns) {
// iterate for all columns collected before
foreach ($allColumns as $column) {
// if one of column in 'allColumns' doesn't exit in $output you added in the correct place adding a zero value
if (!in_array($column, array_keys($columns))) {
$output[$row][$column] = 0;
}
}
}
To print the output you should only iterate over $ouput
This will be the array internally:
(
[t1] => Array
(
[s1-1] => 1
[s1-2] => 1
[s2-1] => 1
[s2-2] => 1
[s3-1] => 0
[s3-2] => 0
)
[t2] => Array
(
[s1-1] => 1
[s2-1] => 2
[s2-2] => 1
[s1-2] => 0
[s3-1] => 0
[s3-2] => 0
)
[t3] => Array
(
[s1-1] => 1
[s2-1] => 1
[s3-1] => 1
[s3-2] => 3
[s1-2] => 0
[s2-2] => 0
)
)
It exists other ways to implement the above, like skip the step where you fill the gaps and do it on the fly, ...
Updated
The simplest way to display the results in a HTML page is by embedding a php script to iterate over the associative array and compose the HTML table (I encourage you to study and research MVC to separate logic from the view)
<!DOCTYPE html>
<?php
// arrays of arrays, I don't know how you receive the data
$arrays = [
['t1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1', 't1-s2-2=1'],
['t2-s1-1=1', 't2-s2-1=2', 't2-s2-2=1'],
['t3-s1-1=1', 't3-s2-1=1', 't3-s3-1=1', 't3-s3-2=3']
];
// bi-dimensional array
$output = [];
// it will store all columns you find in the $arrays entry
$allColumns = [];
// iterate for every array you receive, i.e. ['t1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1', 't1-s2-2=1']
foreach ($arrays as $array) {
// iterate over every element in the array: 't1-s1-1=1', 't1-s1-2=1', 't1-s2-1=1' and 't1-s2-2=1'
foreach ($array as $item) {
// extract the parts on every element: $matches is an array containing the different parts
preg_match('/^(t\d+)-(s\d+-\d+)=(\d+)/', $item, $matches);
/**
* $matches[0] would contains the element if matched: 't1-s1-1=1'
* $matches[1] would contains 't1' if matched
* $matches[2] would contains 's1-1' if matched
* $matches[2] would contains 1 (integer) if matched
*/
if (!empty($matches)) {
$output[$matches[1]][$matches[2]] = $matches[3];
$allColumns[] = $matches[2];
}
}
}
// clean duplicates
$allColumns = array_unique($allColumns);
// sort values alphabetically
sort($allColumns);
// iterate over the just created bi-dimensional array
foreach ($output as $row => $columns) {
// iterate for all columns collected before
foreach ($allColumns as $column) {
// if one of column in 'allColumns' doesn't exit in $output you added in the correct place adding a zero value
if (!in_array($column, array_keys($columns))) {
$output[$row][$column] = 0;
}
}
}
?>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Table Page</title>
</head>
<body>
<table>
<thead>
<?php
echo '<tr><th>Test</th>';
foreach ($allColumns as $head) {
echo sprintf('<th>%s</th>', $head);
}
echo '</tr>';
?>
</thead>
<tbody>
<?php
foreach ($output as $key => $columns) {
echo sprintf('<tr><td>%s</td>', $key);
foreach ($columns as $column) {
echo sprintf('<td>%s</td>', $column);
}
echo '</tr>';
}
?>
</tbody>
</table>
</body>
</html>
Try the following:
$final_array = array();
$temp_array = array();
foreach ($t1 as $t) {
$isin = 0;
$expression = substr($t, 0, strpos($t, "="));
$expression = str_replace("t1-", "" , $expression)
$value = substr($t, strpos($t, "=") + 1);
for ($i = 0; $i < 3; $i++) {
foreach ($x = 0; $x < 3; $x++) {
if ($expression == "s{$i}-{$x}") {
$isin = 1;
array_push($temp_array, $value);
}
}
}
if ($isin == 0) { array_push($temp_array, "X"); }
}
array_push($final_array, $temp_array);
It's not a great solution because you're choosing to do this in a really odd way but you should see the gist of what how to get what you want from this example.
I'm working on an algorithm to calculate the amount of levels in an array of arrays.
The reason I need this is because I need to fetch a list of categories from the database that belongs to a category parent, and depending of the amount of levels this array has, I need to display an amount of category lists (to select categories).
So it would be a category list for each level of categories, for example
Vehicles
Cars
honda
Red
Blue
Yellow
ford
Red
suzuki
Red
Green
BMW
Motorcycles
bla bla
bla bla
Groceries
Fruits
Berries
Red
Strawberries
So I need a function to check the amount of levels of the selected parent, for example if i pass the ID of vehicles i want it to return 4 or 3 if we count Vehicles as level 0, so I know that if the client selected Vechicles from the first list I will have to display 3 more lists.
So far, what I have that is not working is
function count_children_level($list_of_children, $start_depth = 0){
// if the data being passed is an array
if(is_array($list_of_children)){
// amount of nodes is equal to the
$max = $start_depth;
foreach($list_of_children as $i){
$result = count_children_level($i, $start_depth + 1);
if ($result > $max){
$max = $result;
}
}
return $max;
}
//if is not array
else {
return $start_depth;
}
}
I really need to understand how this works because i have to work with several functions like this one, so please if you can, explain your answer in detail.
Thanks
The depth of a nested array is equal to the depth of the largest array in it + 1.
So for your recursive function, instead of passing the entire array every time, you can make an actual recursive call that only gets the depth of the sub-array. So this function returns 1 for a normal, flat array and 1 extra for each level.
<?php
function array_depth($array) {
// Determine largest sub-array. Start with 0 if there are no arrays at all.
$max = 0;
foreach ($array as $item) {
if (is_array($item)) {
// Make the recursive call, passing not $array, but the sub-array ($item)
// to the function again.
$depth = array_depth($item);
if ($depth > $max)
$max = $depth;
}
}
// Depth of this array is the depth of the largest sub-array + 1.
return $max + 1;
}
I called it like this:
echo array_depth(
array('x' =>
array('y' =>
array('z')))); // Returns 3.
My interpretation of what #GolezTrol said in their answer ("The depth of a nested array is equal to the depth of the largest array in it + 1"):
function array_depth($a)
{
// If $a is not an array or it's an empty array then its depth is 1
if (! is_array($a) || count($a) == 0) {
return 0;
}
// Otherwise, add 1 to the maximum depth of the elements it contains
return 1 + max(array_map('array_depth', $a));
}
Another solution with the RecursiveIteratorIterator class. In this way you don't need a recursive function:
$array = array(
'Vehicles' => array(
'Cars' => array(
'honda' => array(
'Red',
'Blue',
'Yellow',
)
)
)
);
function getTotalDepth($array) {
$iterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array)
);
$max = 0;
foreach ($iterator as $element) {
if (!$iterator->callHasChildren()) {
$max = max($max, $iterator->getDepth());
}
}
return $max;
}
echo getTotalDepth($array);
Also very helpful if you want to iterate the complete array:
$iterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator($array),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $element) {
print_r($element);
echo '<br>';
}
I have the following multidimensional array:
<? $array = array(0 => 2, 3 => 1, 5 => 1 );
Which looks like this when printed:
Array ( [0] => 2 [3] => 1 [5] => 1 ); //the value in brackets is the shoe size
The first part of array is a "shoe size", and the second part of the array is the number available in inventory.
I am trying to print out a table that lists all shoe sizes (even if not in the array), and then loop through to provide "number available" in inventory.
Here's what I have so far, but isn't working:
<?php
$array = array(0 => 2, 3 => 1, 5 => 1 );
print ('<table>');
print ('<thead><tr><th>Shoe Size</th>');
for ($i=3; $i<=12; $i += .50) {
print ('<th>'.$i.'</th>');
}
print('</tr></thead>');
print('<tbody><td>Total</td>');
foreach ($array as $shoe_size=>$number_in_inventory) {
for ($i=3; $i<=12; $i += .50) {
if ($i == $shoe_size) {
print('<td>'.$number_in_inventory.'</td>');
}
else {
print('<td>0</td>');
}
}
}
print("</tbody></table>");
My problem is, because I have a foreach loop AND a for loop, it is printing out twice the number of table columns (<td>'s).
How can I better adjust this code so that it only loops through and correctly displays the columns once? I am pretty lost on this one.
Many thanks!
Change your main loop to go through each possible shoe size; if the size exists in the inventory array ($array) then print that value, else print zero.
// ...
print('<tbody><td>Total</td>');
for ($i = 3; $i <= 12; $i += .50) {
if (array_key_exists("$i", $array)) {
print '<td>'.$array["$i"].'</td>';
} else {
print '<td>0</td>';
}
}
// ...
My problem is, because I have a foreach loop AND a for loop, it is printing out twice the number of table columns ('s).
That is precisely the problem. Just like with the <th> section, you want to print a <td> for each of the possible shoe sizes (3 through 12). For each possible shoe size, all you need to do is check to see whether there is a corresponding value in the inventory as my snippet above does.
You might try looping through all the sizes and then for each size, check to see if it's in the array using array_key_exists()