Extract cell value from table based on another cells value - php

HTML file:
http://www.arifoorum.com/test/html.htm
I got this html contents with simplehtmldom library:
array(66) {
[0]=>
array(14) {
[0]=>
string(4) "Item"
[1]=>
string(11) "Date, time:"
[2]=>
string(8) "mõõdikud"
[3]=>
string(6) "Name 2"
[4]=>
string(6) "Name 3"
[5]=>
string(9) "Meter ID:"
[6]=>
string(6) "V_HeEn"
[7]=>
string(6) "U_HeEn"
[8]=>
string(3) "V_V"
[9]=>
string(3) "U_V"
[10]=>
string(6) "V_InTe"
[11]=>
string(6) "U_InTe"
[12]=>
string(6) "V_OuTe"
[13]=>
string(6) "U_OuTe"
}
[1]=>
array(14) {
[0]=>
string(1) "1"
[1]=>
string(19) "24.01.2013 22:23:33"
[2]=>
string(9) "Meter 002"
[3]=>
string(6) " "
[4]=>
string(6) " "
[5]=>
string(8) "40380040"
[6]=>
string(6) " "
[7]=>
string(6) " "
[8]=>
string(6) " "
[9]=>
string(6) " "
[10]=>
string(6) " "
[11]=>
string(6) " "
[12]=>
string(6) " "
[13]=>
string(6) " "
}
[2]=>
...
}
}
Full output: http://www.arifoorum.com/test/test.php
How do I get certain element from that array?
For example: lets say i want value where mõõdikud = 01 and name 2 = külm (that should be 72,114) .
Thanks

This could be useful for other users, so I made a little function that gets the value of a cell from a table, based on values of other cells (conditions):
function getCellValue(DOMElement $table, $cellName = null, array $conditions = array()){
// get all table rows
$trs = $table->getElementsByTagName('tr');
// assume first TR is the table header
$head = $trs->item(0);
// find cell names and their index
$keys = array();
foreach($head->childNodes as $th)
if(!($th instanceof DomText))
$keys[] = trim($th->nodeValue);
if($invalidKeys = array_diff(array_keys($conditions), $keys))
throw new Exception(sprintf('Non-extistent key(s) in table: ', implode(', ', $invalidKeys)));
// find the row that meets all conditions
$targetRow = null;
foreach($table->childNodes as $tr){
// internal counter because we can't rely on DOM index
$idx = 0;
foreach($tr->childNodes as $td){
if($td instanceof DomText)
continue;
$value = trim($td->nodeValue);
// check if all conditions match
if(array_key_exists($keys[$idx], $conditions))
$targetRow = ($value != $conditions[$keys[$idx]]) ? null : $tr;
$idx++;
}
// stop if we found a match
if($targetRow)
break;
}
if(!$targetRow)
throw new Exception('No row matches your conditions');
// build an array with row cells
$values = array();
$idx = 0;
foreach($targetRow->childNodes as $td)
if(!($td instanceof DomText))
$values[$keys[$idx++]] = trim($td->nodeValue);
// return the cell value if a specific cell was requested
if($cellName !== null)
return isset($values[$cellName]) ? $values[$cellName] : null;
// otherwise return all values from the matched row
return $values;
}
It uses DomDocument because the question wasn't tagged as simplehtmldom
#OP: in your case you would use it like:
$html = file_get_contents('http://www.arifoorum.com/test/html.htm');
$dom = new DomDocument();
$doc->preserveWhiteSpace = false;
$dom->loadHtml($html);
$table = $dom->getElementsByTagName('table')->item(0);
print getCellValue($table, 'V_V', array(
'mõõdikud' => '01',
'Name 2' => 'külm',
));

Related

How to get max and min value in a multidimensional array

I have this array :
array(8) {
[0]=>
array(2) {
["ticket_type"]=>
string(9) "normal"
["ticket_price"]=>
string(5) "82.00"
}
[1]=>
array(2) {
["ticket_type"]=>
string(9) "cheaper"
["ticket_price"]=>
string(5) "62.00"
}
[2]=>
array(2) {
["ticket_type"]=>
string(9) "normal"
["ticket_price"]=>
string(6) "182.00"
}
[3]=>
array(2) {
["ticket_type"]=>
string(9) "cheaper"
["ticket_price"]=>
string(6) "162.00"
}
[4]=>
array(2) {
["ticket_type"]=>
string(9) "normal"
["ticket_price"]=>
string(6) "103.00"
}
[5]=>
array(2) {
["ticket_type"]=>
string(9) "cheaper"
["ticket_price"]=>
string(5) "63.00"
}
[6]=>
array(2) {
["ticket_type"]=>
string(9) "normal"
["ticket_price"]=>
string(6) "203.00"
}
[7]=>
array(2) {
["ticket_type"]=>
string(9) "cheaper"
["ticket_price"]=>
string(6) "163.00"
}
}
I want to get the min and max price for "normal" and "cheap" ticket category, there will be more ticket categories, so can't hard code it, will get from DB, how can I do that? I'm using PHP 5.6 now, need export as array or json, Let me know if need more details.
Thank you
You can do it at the SQL level:
SELECT MIN(ticket_price) AS min_ticket_price, MAX(ticket_price) as max_ticket_price, ticket_type
FROM {your_table_name}
WHERE {your_conditions}
GROUP BY ticket_type
If you still want to do it in PHP you can just loop the array and to sort the ticket types then get the min and max values.
foreach($arr as $ticket){
$new[$ticket["ticket_type"]][] = $ticket["ticket_price"];
}
// loop the new array to only get the max and min values of each ticket type
foreach($new as $key => $n){
$res[$key]["max"] = max($n);
$res[$key]["min"] = min($n);
}
output:
array(2) {
["normal"]=>
array(2) {
["max"]=>
string(6) "203.00"
["min"]=>
string(5) "82.00"
}
["cheaper"]=>
array(2) {
["max"]=>
string(6) "163.00"
["min"]=>
string(5) "62.00"
}
}
https://3v4l.org/RcCHZ
Here is a solution to do on the php level:
$prices = [
["ticket_type"=>"normal", "ticket_price"=>"82.00"],
["ticket_type"=>"cheaper", "ticket_price"=>"62.00"],
["ticket_type"=>"normal", "ticket_price"=>"182.00"],
["ticket_type"=>"cheaper", "ticket_price"=>"162.00"],
["ticket_type"=>"normal", "ticket_price"=>"103.00"],
["ticket_type"=>"cheaper", "ticket_price"=>"63.00"],
["ticket_type"=>"normal", "ticket_price"=>"203.00"],
["ticket_type"=>"cheaper", "ticket_price"=>"163.00"],
];
// STEP:1 group by ticket types
$grouped_array = [];
foreach($prices as $price) {
$ticket_type = $price["ticket_type"];
$grouped_array[$ticket_type][] = $price["ticket_price"];
}
/*
$grouped_array = [
"normal" => ["82.00", "182.00", "103.00", "203.00"],
"cheaper => ["62.00", "162.00", "63.00", "163.00"]
];
*/
function minMax($type_array) {
$min_max = ['min'=> min($type_array), 'max'=>max($type_array)];
return $min_max;
}
// STEP 2: find min and max in each category
$min_max = [];
foreach($grouped_array as $type => $prices) {
$min_max[$type] = minMax($prices);
}
/*
$min_max = [
"normal" => ["min"=>"82.00", "max"=>"203.00"],
"cheaper => ["min"=>"62.00", "max"=>"163.00"]
];
*/
However, doing it on the database layer is best in your case. this answers "How to get max and min value in a multidimensional array".

parse php file and get dates

I am trying to parse a csv file in php to try and figure out how to get all data between some dates and the sort according to the date in ascending order but I am not able to sort the date column or I have no idea what format it is in please help
ID Reg Date FirstName LastName
1 1278336015 Sergio Roberto
2 1395656121 Ray Wilkins
3 1300276526 Trueman Ted
4 1374087492 Volt John
Please assist thanks
Okay, just for fun.
1. Parse the Data:
You could load the CSV data into an associative array like this (admittedly not very sophisticated, no error checking, validation etc):
$file = file_get_contents('CSV.csv'); // load csv into string
$rows = explode(PHP_EOL, $file); // break each line into array
$data = Array(); // where we'll store the data
foreach ($rows as $i => $row) {
$fields = explode(',', $row); // break each field into array
foreach ($fields as $col => $val) {
if ($i == 0) {
$names[] = $val; // headers in first row
} else {
$colName = $names[$col];
if ($colName == 'Reg Date') $val = date('Y-m-d H:i:s', $val);
$data[$i - 1][$colName] = $val;
}
}
}
So with your sample data above, you get:
array(4) {
[0]=>
array(4) {
["ID"]=>
string(1) "1"
["Reg Date"]=>
string(19) "2010-07-05 06:20:15"
["FirstName"]=>
string(6) "Sergio"
["LastName"]=>
string(7) "Roberto"
}
[1]=>
array(4) {
["ID"]=>
string(1) "2"
["Reg Date"]=>
string(19) "2014-03-24 03:15:21"
["FirstName"]=>
string(3) "Ray"
["LastName"]=>
string(7) "Wilkins"
}
[2]=>
array(4) {
["ID"]=>
string(1) "3"
["Reg Date"]=>
string(19) "2011-03-16 04:55:26"
["FirstName"]=>
string(7) "Trueman"
["LastName"]=>
string(3) "Ted"
}
[3]=>
array(4) {
["ID"]=>
string(1) "4"
["Reg Date"]=>
string(19) "2013-07-17 11:58:12"
["FirstName"]=>
string(4) "Volt"
["LastName"]=>
string(4) "John"
}
}
2. Sort the Data:
You can use usort() to sort by the timestamp column.
usort($data, function ($a, $b) {
if ($a['Reg Date'] == $b['Reg Date']) return 0;
return ($a['Reg Date'] < $b['Reg Date']) ? -1 : 1;
});
Results:
===After Sorting:===
array(4) {
[0]=>
array(4) {
["ID"]=>
string(1) "1"
["Reg Date"]=>
string(19) "2010-07-05 06:20:15"
["FirstName"]=>
string(6) "Sergio"
["LastName"]=>
string(7) "Roberto"
}
[1]=>
array(4) {
["ID"]=>
string(1) "3"
["Reg Date"]=>
string(19) "2011-03-16 04:55:26"
["FirstName"]=>
string(7) "Trueman"
["LastName"]=>
string(3) "Ted"
}
[2]=>
array(4) {
["ID"]=>
string(1) "4"
["Reg Date"]=>
string(19) "2013-07-17 11:58:12"
["FirstName"]=>
string(4) "Volt"
["LastName"]=>
string(4) "John"
}
[3]=>
array(4) {
["ID"]=>
string(1) "2"
["Reg Date"]=>
string(19) "2014-03-24 03:15:21"
["FirstName"]=>
string(3) "Ray"
["LastName"]=>
string(7) "Wilkins"
}
}
3. Filter the Data:
And you can use array_filter to filter the results down. I created a class to handle this (as described by #jensgram answer here)
$from = '2011-01-01';
$to = '2013-12-31';
$filtered = array_filter($data, Array(new compareDates($from, $to), 'isInRange'));
Results:
===After Filtering [2011-01-01 - 2013-12-31]:===
array(2) {
[1]=>
array(4) {
["ID"]=>
string(1) "3"
["Reg Date"]=>
string(19) "2011-03-16 04:55:26"
["FirstName"]=>
string(7) "Trueman"
["LastName"]=>
string(3) "Ted"
}
[2]=>
array(4) {
["ID"]=>
string(1) "4"
["Reg Date"]=>
string(19) "2013-07-17 11:58:12"
["FirstName"]=>
string(4) "Volt"
["LastName"]=>
string(4) "John"
}
}
Here's the simple class I used:
class compareDates
{
function __construct($from, $to)
{
$this->from = $from;
$this->to = $to;
}
function isInRange($ele)
{
if ($ele['Reg Date'] >= $this->from && $ele['Reg Date'] <= $this->to) {
return TRUE;
}
return FALSE;
}
}
NOTE: for the purpose of being able to see the date/time, I stored as
a string. But you would normally just use the numeric value to sort
by. I mention this to say that if you change the format of the date
string, it could break the sorting.

How can I filter data from my array php?

I am really struggling filtering my data.I know how to access parts of the array but am struggling on how to filter. I know how to do it in SQL SUM & count) but not when it comes to PHP arrays please help.
I need to filter some of my data stored in the variable $res.
I need to see how many times each 'REF' appears & total 'LCL_D_CBM' for each ref all of this where the "TERR" is equal to "TERR1".
foreach ($res as $res1){
if ($res1["TERR"] == "TERR1"){
//the individual ref
//$res1['REF'];
// the coutn of how many times each ref appears
//echo count($res1['REF']);
//sum
//echo array_sum($res1['LCL_D_CBM']);
}
}
need result to be like -
CEA
3
2561
CEF
456
135
var_dump($res); gives me below
array(350) {
[0]=> array(7) { [0]=> string(3) "CEA" ["REF"]=> string(3) "CEA" [1]=> string(5) "1.080" ["LCL_D_CBM"]=> string(5) "1.080" [2]=> string(3) "WF2" ["AREA_CODE"]=> string(3) "WF2" ["TERR"]=> string(5) "TERR1" }
[1]=> array(7) { [0]=> string(3) "CEA" ["REF"]=> string(3) "CEA" [1]=> string(5) "2.000" ["LCL_D_CBM"]=> string(5) "2.000" [2]=> string(4) "HU13" ["AREA_CODE"]=> string(4) "HU13" ["TERR"]=> string(5) "TERR1" }
[2]=> array(7) { [0]=> string(3) "CEF" ["REF"]=> string(3) "CEA" [1]=> string(5) "2.448" ["LCL_D_CBM"]=> string(5) "2.448" [2]=> string(4) "TW16" ["AREA_CODE"]=> string(4) "TW16" ["TERR"]=> string(5) "TERR2" } ..... etc
You can solve it like this. Not a pretty solution, but should do the work. (I did not test this, so it might contain a spelling error or something):
$sum_lcl = 0;
$unique_refs = array();
foreach ($res as $res1){
if (!array_key_exists($res1['REF'], $unique_refs)) {
$unique_refs[$res1['REF']] = array();
}
$unique_refs[$res1['REF']]['SUM'] = ( array_key_exists('SUM', $unique_refs[$res1['REF']]) ) ? ( intval( $unique_refs[$res1['REF']]['SUM'] ) + 1 ) : 1;
$unique_refs[$res1['REF']]['LCL_SUM'] = ( array_key_exists('LCL_SUM', $unique_refs[$res1['REF']]) ) ? ( floatval( $unique_refs[$res1['REF']]['LCL_SUM'] ) + floatval( $res1['LCL_D_CBM'] ) ) : 1;
}
foreach( $unique_refs AS $unique => $data ){
$title = $unique;
$sum = $data['SUM'];
$lcl_sum = $data['LCL_SUM'];
echo "{$title}<br />{$sum}<br />{$lcl_sum}";
}

Show only unique values from Array

I have the following array in php:
array(12) {
[0]=>
array(2) {
["adress"]=>
string(17) "Kungsvägen 118 A "
["dob"]=>
string(10) "1969-06-17"
}
[1]=>
array(2) {
["adress"]=>
string(14) "Skolgatan 1 B "
["dob"]=>
string(10) "1969-06-17"
}
[2]=>
array(2) {
["adress"]=>
string(14) "Skolgatan 1 B "
["dob"]=>
string(10) "1980-05-22"
}
[3]=>
array(2) {
["adress"]=>
string(12) "Myntvägen 8 "
["dob"]=>
string(10) "1980-05-22"
}
[4]=>
array(2) {
["adress"]=>
string(14) "Skolgatan 1 B "
["dob"]=>
string(10) "1993-05-09"
}
[5]=>
array(2) {
["adress"]=>
string(14) "Skolgatan 1 B "
["dob"]=>
string(10) "1989-06-28"
}
[6]=>
array(2) {
["adress"]=>
string(14) "Skolgatan 1 B "
["dob"]=>
string(10) "1991-03-17"
}
[7]=>
array(2) {
["adress"]=>
string(14) "Skolgatan 1 B "
["dob"]=>
string(10) "1989-10-30"
}
[8]=>
array(2) {
["adress"]=>
string(23) "Gasslanda VÄSTERGÅRD 2 "
["dob"]=>
string(10) "1980-10-30"
}
[9]=>
array(2) {
["adress"]=>
string(14) "Skolgatan 1 B "
["dob"]=>
string(10) "1980-10-30"
}
[10]=>
array(2) {
["adress"]=>
string(14) "Skolgatan 1 B "
["dob"]=>
string(10) "1990-05-01"
}
[11]=>
array(2) {
["adress"]=>
string(11) "Ågatan 6 A "
["dob"]=>
string(10) "1990-05-01"
}
}
I want to print out the unique adress-values in this array when I'm doing an foreach. As you can see, Skolgatan 1 B appears several times in the array, so I want to print it out just once in my loop. How can I do this? I have tried
array_unique([$newArray['adress']);
but that does not work.
$unique = array();
foreach($array as $item)
$unique[$item['adress']] = $item;
Then use $unique
Something like this should work:
$printed_vals = array();
foreach ($array as $item) {
if (!in_array($item['adress'], $printed_vals)) {
print_r($item);
$printed_vals[] = $item['adress'];
}
}
This is how I would have solved this problem. Hope it helps.
$non_duplicates = array();
$i=0;
foreach( $addresses AS $address ){
if( !in_array( $address['adress'], $non_duplicates ) ){
// Use one of the below array_push statements
array_push( $non_duplicates, $i ); // if you want to get the array key position
array_push( $non_duplicates, $address['adress'] ); // if you only want a new array of unique addresses
}
$i++;
}
If you have chosen to only return key positions to $non_duplicates yo can then retrieve your unique positions from you array by:
foreach( $non_duplicates AS $key ){
echo $addresses[$key];
}
I guess you want to print address once but dob in multiple times.. in that case you can do something like followings
$printed_vals = array();
foreach ($array as $item) {
$printed_vals[$item['adress']][] = $item['dob'];
}
foreach ($printed_vals as $address => $values) {
echo $address . " => " . implode(",", $values);
}

Multidimensional array search using another element value

I have a multi dimensional array built dynamically.
Is it possible to get the value of an element by using another element.
e.g : search with idQ = 26 and get in return value its neighbor element values like :: idA=>49 and A=>500-10000
[0]=>
array(5) {
["idQA"]=>
string(3) "194"
["idQ"]=>
string(2) "26"
["Q"]=>
string(58) "Imposition supérieur
à 2500€ d’impôts annuel"
["idA"]=>
string(2) "49"
["A"]=>
string(10) "5000-10000"
}
[1]=>
array(5) {
["idQA"]=>
string(3) "173"
["idQ"]=>
string(2) "22"
["Q"]=>
string(20) "Si oui, laquelle(s):"
["idA"]=>
string(2) "32"
["A"]=>
string(7) "Voiture"
}
Example array :: https://gist.github.com/anonymous/9234703
Yes, like:
$founded = 0;
foreach($my_array[1] as $key => $val) {
if ($val == "something_to_search") {
$founded = $key;
break;
}
}
$before = $my_array[1][$founded-1];
$after = $my_array[1][$founded+1];

Categories