I have this partially working. I need to grab the data of each player, and present a variable for each "cricket" and "x01" games. I am able to grab the data from the top table, however the 2nd one is not showing any data in my code. I am probably missing something simple, but I can't figure it out.
I want the output to show like this. The part under the line break is what I am missing.
"Howard Hill": {
"name": "Howard Hill",
"team": "Team 2",
"ppd_01": "34.54",
"games_01": "153",
"wins_01": "999",
"assists_01": "69",
"sspre_01": "7.876",
"mpr_crk": "9.99",
"games_crk": "999",
"wins_crk": "999",
"assists_crk": "99",
"sspre_crk": "9.999"
}
Here is my code
<?php
ini_set('default_socket_timeout', 180); // 900 Seconds = 15 Minutes
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->loadHTML(file_get_contents('http://freerdarts.com/past_stats/tues-2018-player-standings.html'));
$doc->strictErrorChecking = false;
$pre = [];
foreach ($doc->getElementsByTagName('table') as $table) {
foreach ($table->getElementsByTagName('tr') as $i => $tr) {
$y = 0;
foreach ($tr->childNodes as $td) {
$text = trim($td->nodeValue);
if ($y > 7) {
unset($pre[$i]);
continue;
}
if (empty($text)) {
continue;
}
$pre[$i][] = $text;
$y++;
}
}
}
// normalise
$pstats = [];
foreach ($pre as $row) {
$pstats[$row[0]] = [
'name' => $row[0],
'team' => $row[1],
'ppd_01' => $row[2],
'games_01' => $row[3],
'wins_01' => $row[4],
'sspre_01' => $row[5],
];
}
echo '<pre>'.json_encode($pstats, JSON_PRETTY_PRINT).'</pre>';
//echo $pstats['Scott Sandberg']['01'];
?>
One problem you're facing is that you're not getting the proper table that needs parsing.
Take note there are multiple tables inside that page.
You need to point out inside the loop that you're skipping other tables in the HTML page and only choose to process the score report table, nothing else:
if (strpos($table->getAttribute('class'), 'report') === false) {
continue;
}
So after getting other tables out of the way, you can start processing the data inside the specific table results that you want to store.
Another thing to point out is you need to skip the headers inside the table. You don't need to anyways.
if ($tr->parentNode->nodeName === 'thead') continue; // skip headers
After that, its just a matter of looping on each <td>.
One gotcha on the tables is that one table has six 6 columns. Another one has 7 so first gather all <td> values. After gathering just unset it from the gathered data so that you have a uniform column layout structure. (I assume you're trying to skip out assists)
Here's the full code:
$pre = []; // initialize container
$keys = ['name', 'team', 'ppd', 'games', 'wins', 'sspre']; // keys needed to be used in the json
foreach ($doc->getElementsByTagName('table') as $table) { // loop all found tables
if (strpos($table->getAttribute('class'), 'report') === false) {
continue; // if its not the report table, skip
}
foreach ($table->getElementsByTagName('tr') as $i => $tr) { // loop each row of report table
if ($tr->parentNode->nodeName === 'thead') continue; // skip headers
$row_values = []; // initialize container for each row
foreach ($tr->childNodes as $td) { // loop each cell
$text = trim($td->nodeValue); //
if ($text === '') continue;
$row_values[] = $text;
}
// unset assist if this table has 7 columns
if (count($row_values) === 7) unset($row_values[5]);
$row_values = array_combine($keys, $row_values); // combine the keys and values
$pre[$row_values['name']] = $row_values; // push them inside
}
}
// finally encode in the end
echo json_encode($pre);
Here's the sample output
I have modified #Ghost code. Try below code.
<?php
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->loadHTML(file_get_contents('http://freerdarts.com/past_stats/tues-2018-player-standings.html'));
$doc->strictErrorChecking = false;
$pre = [];
$keys = ['name', 'team', 'ppd', 'games', 'wins', 'sspre'];
$keys2 = ['name', 'mpr', 'games', 'wins','assists', 'sspre'];
foreach ($doc->getElementsByTagName('table') as $k => $table) {
if (strpos($table->getAttribute('class'), 'report') === false) {
continue;
}
foreach ($table->getElementsByTagName('tr') as $i => $tr) {
if ($tr->parentNode->nodeName === 'thead') continue; // skip headers
$row_values = [];
foreach ($tr->childNodes as $td) {
$text = trim($td->nodeValue);
if ($text === '') continue;
$row_values[] = $text;
}
if($k == 1 ){
$row_values = array_combine($keys, $row_values);
}elseif($k == 2 ){
unset($row_values[1]);
$row_values = array_combine($keys2, $row_values);
}
$pre[$row_values['name']][] = $row_values;
}
}
$new_arr = [];
foreach($pre as $name => $row){
$new_arr[$name] = [
"name"=> $name,
"team"=> $row[0]['team'],
"ppd_01" => $row[0]['ppd'],
"games_01" => $row[0]['games'],
"wins_01" => $row[0]['wins'],
"sspre_01" => $row[0]['sspre'],
"mpr_crk" => $row[1]['mpr'],
"games_crk" => $row[1]['games'],
"wins_crk" => $row[1]['wins'],
"assists_crk" => $row[1]['assists'],
"sspre_crk" => $row[1]['sspre']
];
}
echo '<pre>'.json_encode($new_arr, JSON_PRETTY_PRINT).'</pre>';
Here is sample output
https://www.tehplayground.com/Du5rId3iRx3NH6UL
It seems to me that you want to combine the x01 table values with the crk table values under the same name. Here is the code that I think you are looking for with an example.
$x01 = [];
$crk = [];
$keys_01 = ['name', 'team', 'ppd_01', 'games_01', 'wins_01', 'sspre_01'];
$keys_crk = ['name', 'team', 'mpr_crk', 'games_crk', 'wins_crk', 'assists_crk', 'sspre_crk'];
$table_num = 1;
foreach ($doc->getElementsByTagName('table') as $table) {
if (strpos($table->getAttribute('class'), 'report') === false) {
continue;
}
foreach ($table->getElementsByTagName('tr') as $i => $tr) {
if ($tr->parentNode->nodeName === 'thead') continue; // skip headers
$row_values = [];
foreach ($tr->childNodes as $td) {
$text = trim($td->nodeValue);
if ($text === '') continue;
$row_values[] = $text;
}
// build x01 array
if ($table_num === 1) {
$row_values = array_combine($keys_01, $row_values);
$x01[$row_values['name']] = $row_values;
// build crk array
} else {
$row_values = array_combine($keys_crk, $row_values);
$crk[$row_values['name']] = $row_values;
}
}
$table_num++;
}
$combined = array_merge_recursive($x01, $crk);
// after arrays are merged, remove duplicate values
foreach ($combined as $name => $value) {
if ($value['name']) {
$combined[$name]['name'] = $name;
}
if ($value['team']) {
$combined[$name]['team'] = $value['team'][0];
}
}
echo json_encode($combined, JSON_PRETTY_PRINT);
Related
I have this code using an api , the first iteration is showing everything right , but at the second iteration is showing the items from the first iteration + the items from the second iteration , and the same thing at the third iteration.
I dont want that , how can i fix that problem ?
$g=0;
foreach ($matches as $match) {
$inside = $api->getMatch('123');
$pp = $api->getMatchTimeline('123');
foreach ($inside->participants as $partId) {
if ($partId->championId == $match->champion) {
$participant_id[] = $partId->participantId;
$participant_idS = $partId->stats->participantId;
foreach ($pp->frames as $p) {
foreach ($p->events as $t) {
if ($t->type == "ITEM_PURCHASED" and $t->participantId == $participant_idS) {
$item_id = $t->itemId;
$d = $api->getStaticItem($item_id);
if($d->depth == 2 or $d->depth == 3){
$itemsMade[] = $d->id;
}
}
}
}
}
}
$dt = [['match_ids' => $part, "champion" => $soloq->champion, "timestamp" => $match->timestamp, "participantId" => $participant_id[$g++], "itens" => json_encode($itemsMade)]
];
echo ' <pre>';
var_dump($dt);
echo '</pre>';
}
You need to set that array to be empty at the start of your loop. Otherwise you just keep adding to it as you see in your output.
foreach ($inside->participants as $partId) {
$itemsMade = [];
I have array of objects, for each objects i have name, category, price and couple other things. and from that array i want to remove objects that has specific category.
public function getCSV()
{
$contents = Storage::disk('dropbox')->get('InventoryReport.csv');
$lines = explode(PHP_EOL, $contents);
$items = array();
// categories to ignore when importing
$ignore = ['Misc', 'Soft Drinks', 'Juices', 'Water', 'Snack', 'Energy Drink', 'Tobacco', 'Gum', 'Account Payment'];
foreach ($lines as $line)
{
$items[] = str_getcsv($line);
}
array_shift($items);
array_pop($items);
// foreach ($items as $item)
// {
// $i = Item::where('upc', $item[7])->first();
// if($i == null)
// {
// $name = str_slug($item[8], '-');
// // $inventory = Item::create(
// // ['upc' => $item[7],
// // 'name' => $item[8],
// // 'price' => $item[9],
// // 'stock' => $item[10],
// // 'cost' => $item[11],
// // 'category' => $item[2],
// // 'slug' => $name
// // ]
// // );
// }
// }
}
above is my code. I want to remove all the items in array that has category thats inside $ignore array. before i store it into database.
Replace this:
foreach ($lines as $line)
{
$items[] = str_getcsv($line);
}
with:
foreach ($lines as $line) {
$item = str_getcsv($line);
if (count($item) > 1 && !in_array($item[2], $ignore)) {
$items[] = $item;
}
}
Now $items will only have the items you are looking for.
NB: Review whether the calls of array_shift and array_pop are still needed, depending on what the category was of those two items.
I need to modify the data structure of json array list as per some key value using PHP. I am explaining my code below.
<?php
$output=array(
array(
"first_name"=>"robin",
"last_name"=>"sahoo",
"reg_no"=>12,
"paper_code"=>"BA001"
),array(
"first_name"=>"robin",
"last_name"=>"sahoo",
"reg_no"=>12,
"paper_code"=>"BA002"
),array(
"first_name"=>"Rama",
"last_name"=>"Nayidu",
"reg_no"=>13,
"paper_code"=>"BA001"
)
);
//echo json_encode($output);
$result=array();
foreach ($output as $key => $value) {
if (count($result)==0) {
$result[]=array(
"name"=>$value["first_name"].' '.$value['last_name'],
"reg_no"=>$value['reg_no'],
"paper1"=>$value['paper_code'],
"paper2"=>"",
"paper3"=>"",
"paper4"=>""
);
}
}
The output of the input array is given below.
// Output:
[
{
"first_name":"robin",
"last_name":"sahoo",
"reg_no":12,
"paper_code":"BA001"
},
{
"first_name":"robin",
"last_name":"sahoo",
"reg_no":12,
"paper_code":"BA002"
},
{
"first_name":"Rama",
"last_name":"Nayidu",
"reg_no":13,
"paper_code":"BA001"
}
];
The above is my array list. Here I need to modify the all row value by reg_no means if there are multiple rows including same reg_no then those will merge with joining the both name and my expected output should like below.
expected output:
[
{
'name':"robin sahoo",
"reg_no":12,
"paper1":"BA001",
"paper2":"BA002",
"paper3":"",
"paper4":""
},
{
'name':"Rama Nayidu",
"reg_no":13,
"paper1":"BA001",
"paper2":"",
"paper3":"",
"paper4":""
}
]
Here paper1,paper2,paper3,paper4 will be selected serially means suppose same reg_no=12 has first row paper_code= BA001 then it will be paper1=BA001 and second row paper_code=BA002 then it will be paper2=BA002 and so on. Here I am using PHP to map this array.
Try the following, Let me know..
$output=array(array("first_name"=>"robin","last_name"=>"sahoo","reg_no"=>12,"paper_code"=>"BA001"),array("first_name"=>"robin","last_name"=>"sahoo","reg_no"=>12,"paper_code"=>"BA002"),array("first_name"=>"Rama","last_name"=>"Nayidu","reg_no"=>13,"paper_code"=>"BA001"));
//echo json_encode($output);
$result=array();
$temp=array();
if(!empty($output)){
foreach ($output as $key => $value) {
if(isset($temp[$value['reg_no']])){
if(empty($temp[$value['reg_no']]["paper1"]) || $temp[$value['reg_no']]["paper1"] == ""){
$temp[$value['reg_no']]["paper1"] = $value['paper_code'];
}else if(empty($temp[$value['reg_no']]["paper2"]) || $temp[$value['reg_no']]["paper2"] == ""){
$temp[$value['reg_no']]["paper2"] = $value['paper_code'];
}else if(empty($temp[$value['reg_no']]["paper3"]) || $temp[$value['reg_no']]["paper3"] == ""){
$temp[$value['reg_no']]["paper3"] = $value['paper_code'];
}else if(empty($temp[$value['reg_no']]["paper4"]) || $temp[$value['reg_no']]["paper4"] == ""){
$temp[$value['reg_no']]["paper4"] = $value['paper_code'];
}
}else{
$temp[$value['reg_no']] = array("name"=>$value["first_name"].' '.$value['last_name'],"reg_no"=>$value['reg_no'],"paper1"=>$value['paper_code'],"paper2"=>"","paper3"=>"","paper4"=>"");
}
}
}
if(!empty($temp)){
foreach ($temp as $key => $value) {
$result[] = $value;
}
}
This Code May help you
<?php
$output=array(array("first_name"=>"robin","last_name"=>"sahoo","reg_no"=>12,"paper_code"=>"BA001"),array("first_name"=>"robin","last_name"=>"sahoo","reg_no"=>12,"paper_code"=>"BA002"),array("first_name"=>"Rama","last_name"=>"Nayidu","reg_no"=>13,"paper_code"=>"BA001"));
//echo json_encode($output);
$result=array();
foreach ($output as $key => $value) {
if (count($result)==0) {
$output[$key]=array("name"=>$value["first_name"].' '.$value['last_name'],"reg_no"=>$value['reg_no'],"paper1"=>$value['paper_code'],"paper2"=>"","paper3"=>"","paper4"=>"");
}
}echo "<pre>";print_r($output);
?>
You can try with this
$result = []; // Initialize result array
foreach ($output as $key => $value) {
$name = $value['first_name'] . ' ' . $value['last_name'];
// check if same name already has entry, create one if not
if (!array_key_exists($name, $result)) {
$result[$name] = array(
'name' => $name,
'reg_no' => $value['reg_no'],
'paper1' => '',
'paper2' => '',
'paper3' => '',
'paper4' => ''
);
}
// count array elements with value, then set paper number and value
$paper = 'paper' . (count(array_filter($result[$name])) - 1);
$result[$name][$paper] = $value['paper_code'];
}
$result = array_values($result); // reindex result array
$result = json_encode($result); // Encode to json format
print_r($result); // print result
This assumes that first_name and last_name is always same for each reg_no
i am using csv importer library to load bulk of products into mysql database with codeigniter. csv file has some column names from one table like name, price and some column names from another table like categories. it inserts name and price to first table and categories will be inserted after we got id from first table, so category will go with id of the product. but this is taking too long to process the csv file (1000 entries = 2 minutes). the code i have put is
$csv_file_data = $this->csvimport->get_array($_FILES['csv']['tmp_name']);
foreach ($csv_file_data as $csv_data) {
$required = array(
'name' => $csv_data['name'],
'price' => $csv_data['price']
);
foreach ($required as $key => $value) {
$this->db->set($key, $value);
}
$categories= array();
foreach ($csv_data as $key => $value) {
if(strstr($key, 'categories')) {
$category = explode('|', $value);
for($i = 0; $i < sizeof($category); $i++) {
array_push($categories, $category[$i]);
}
}
}
$this->db->insert('first_table');
$id = $this->db->insert_id();
foreach ($categories as $metatag) {
$this->db->set('productid', $id);
$this->db->set('category', $metatag);
$this->db->insert('second_table');
}
}
but it is taking too long to process only 1000 entries, how to optimize this to process 5000 entries in less than 20-30 seconds ?
I believe this is what you're after ...
$csv_file_data = $this->csvimport->get_array($_FILES['csv']['tmp_name']);
foreach ($csv_file_data as $csv_data) {
$required = array(
'name' => $csv_data['name'],
'price' => $csv_data['price']
);
$this->db->set($required);
$categories = array();
foreach ($csv_data as $key => $value) {
if (strstr($key, 'categories')) {
$category = explode('|', $value);
for ($i = 0; $i < sizeof($category); $i++) {
$categories[] = $category[$i];
}
}
}
$this->db->insert('first_table');
$bulk = array();
$id = $this->db->insert_id();
foreach ($categories as $metatag) {
$bulk[] = array(
'category' => $metatag,
'productid' => $id,
);
}
$this->db->insert_batch('table2', $bulk);
}
Note the use of insert_batch which will dramatically improve your speed and also you can give set() an array.
Can you try a version like this and tell me if this is working and return me the time for 100 rows ?
$bulk = [];
$csv_file_data = $this->csvimport->get_array($_FILES['csv']['tmp_name']);
$required = [];
foreach ($csv_file_data as $csv_data) {
$bulk = [];
$id = $this->db->insert_id();
$required[] = [
'name' => $csv_data['name'],
'price' => $csv_data['price'],
];
foreach ($csv_data as $key => $value) {
if (false !== strpos($key, 'categories')) {
$category = explode('|', $value);
foreach ($category as $metatag) {
$bulk[] = [
'category' => $metatag,
'productid' => $id,
];
}
}
}
}
$this->db->insert_batch('first_table', $required);
$this->db->insert_batch('second_table', $bulk);
I couldn't understand the multidimensional array in PHP properly. I have a CSV file having two columns as shown below:
I am trying to create an array of array, in which each key is a cataegory. However, the value of each key is an array. In this array, each key is company and value is the count of the product. See below the code:
<?php
//array contains value
function contains_value($my_array, $value_search){
foreach ($my_array as $key => $value) {
if ($value === $value_search)
return true;
}
return false;
}
//array contains key
function contains_key($my_array, $key_search){
foreach ($my_array as $key => $value) {
if ($key === $key_search)
return true;
}
return false;
}
$handle = fopen("product_list.csv", "r");
$products = array();
if ($handle) {
while (($line = fgets($handle)) !== false) {
$product = explode(",", $line);
$category = $product[0];
$company = $product[1];
if (contains_key($products, $category)) {
if (contains_value($products, $company)) {
//increase the count of category by 1
$products[$category][$company] = $products[$category][$company] + 1;
} else {
//append new company with count 1
array_push($products[$category], array(
$company,
1
));
}
} else {
//initialize new company with count 1
$products[$category] = array(
$company,
1
);
}
}
fclose($handle);
}
var_dump($products);
?>
I noticed that the var_dump($products) is not showing correction information. I am expecting following kind of result:
I haven't enough reputation to reply, but I think he need counts.
To complete the answer of Alive to Die, more something like this:
if (!array_key_exists($category, $products)) {
products[$category] = [];
}
if (!array_key_exists($company, $products[$category])) {
products[$category][$company] = 0;
}
++$results[$cataegory][$company];
But cleaner ;)
Edit:
If I remember well, his first idea was this:
$products[$category][] = $company;
The code is shorter. Maybe you can combine the two ideas.