Algorithm in finding valid and non-duplicate entries in php - php

I am currently using php to help me find the valide and non-duplicated entry,
which i need
a list of valid and non-duplicated
entry a list of invalid input (unique)
a list of duplicate input
My approach is first create 5 array 2 for orginal ,1 for no mistake (empty),
1 for valid (empty) , 1 for duplicate (empty)
First using one of orginal array, for each one element : check valid
and check duplicate, if invalid , put into invalid array , and check duplicate by using inarray
after all, i get one array of invalid and duplicate , then using the orginal array, check which element is not in that two array. And job done.
My problem is, it seems quite inefficiency, how can i improve it? (Perferable if using some famous algorithm)
Thank you.
// get all duplicate input and store in an array
for ($row = 1; $row <= $highestRow; $row++) {
for ($y = 0; $y < $highestColumn; $y++) {
$val = $sheet->getCellByColumnAndRow($y, $row)->getValue();
//use reg exp to check whether it is valid
if ($y == $mailColumn && !preg_match($pattern,$val))
{$invaild[]=$row;}
//if valid, test whether it is duplicate
elseif ($y == $mailColumn && in_array($val,$email))
{$duplicate[]=$val;
$duplicate[]=$row;}
if ($y == $mailColumn)
{$email[]=$val;
$email=array_unique($email);}
}
}
// unique invalid array since i just need invalid inputs, not the invalid + duplicate input
$invaild=array_unique($invaild);

try this:
<?php
echo "<pre>";
$array1 = array("a#b.com","c","c","d#e.com","test1","","test3","test2","test3");
$array_no_mistake = array_filter($array1,function($subject){if(trim($subject)=="") return true;});
$array_uniq = array_diff(array_unique($array1),$array_no_mistake);
$array_dups = array_diff_assoc(array_diff($array1,$array_no_mistake),$array_uniq);
$array_valid = array_filter($array_uniq,function($subject){
if (preg_match('/\A(?:[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z/i', $subject)) {
return true;
} else {
return false;
}
});
$array_invalid = array_diff_assoc($array_uniq,$array_valid);
print_r($array1);
print_r($array_no_mistake);
print_r($array_uniq);
print_r($array_dups);
print_r($array_valid);
print_r($array_invalid);
?>

1) It would seem you are only interested in the email columns so i think there is no point in iterating over all of the other columns (so the inner loop is basically redundant).
2) You can use associative arrays in order to store emails as indexes and later on efficiently look for duplicates by checking for the existence of the index/email in the array.
Here's an example:
$valid = array();
$invalid = array();
$dups = array();
for ( $row = 0; $row < $highestRow; $row++ )
{
$email = $sheet->getCellByColumnAndRow( $mailColumn, $row )->getValue();
if ( !preg_match( $pattern, $email ) )
{
$invalid[] = $row;
}
else if ( isset( $dups[ $email ] ) )
{
$dups[ $email ][] = $row;
}
else
{
$dups[ $email ] = array();
$valid[] = $row
}
}
At the end of this, $invalid will hold a list of all of the invalid rows, $dups will hold an array of arrays, each indicating the rows in which the current email is the index and its value is an array which lists the rows that share this email. If the array at a certain index is empty, the email is not duplicated.
$valid will hold the numbers of the valid rows.
Now fancy algorithm, sorry...

Related

Create a temporary array in PHP to add to a larger array

I am trying to create a number of arrays to add to a larger array which I will then index two dimensionally (for example my_array[i][j]).
I believe I am having some type of pointing issue... I am iterating through a loop.... at the top of each iteration I instantiate a new array with the same name. When I try and view the output each item in the array appears blank.
Is there a better way for me to instantiate the "temp" arrays to fill the larger (outer) array? Really appreciate any and all help, this community has helped me through so many questions :D
$main_array = array();
for($i = 0; $i < $member_count; $i++)
{
$temp_array = array();
//preform SQL query here
$sql_get_member_transactions = 'some SQL query to go to my DB';
foreach($sql_get_member_transactions as $row)
{
//cannot get array to update here
array_push($temp_array, $row['amount']);
}
array_push($main_array, $temp_array);
}
#***FULL CODE BELOW***
$club_transactions = array();
for($i = 0; $i < $member_count; $i++)
{
#create an array for each member in the club,
#add each memeber's array to a larger array once filled with deposit amounts
#here check if member had a deposit (later we will check ALL transaction types...)
#if no deposit on that date add a zero to their array
$temp_member_transactions = array();
$temp_member = my_members[$i];
$sql_member_transactions = "SELECT * FROM Transactions WHERE Date >= '$first_t_date' AND Date <= '$last_t_date' AND RelatedClubID = 'THH'";
$sql_get_member_transactions = mysqli_query($conn, $sql_member_transactions);
//here we will get all transactions that lie within the
//event-transaction-date-window... in otherwords, the date window
//in the year where members transactions occured
foreach($sql_get_member_transactions as $row)
{
//we only want to include the transaction amount
//in the member-specific array if it belongs to that member
//otherwise see "else"
if($row['T_Owner'] == $temp_member)
{
$z = $row['T_Amount'];
}
else
{
//set to 0 so that we still account for the transaction date
$z = 0;
}
array_push($temp_member_transactions, $z);
}
array_push($club_transactions, $temp_member_transactions );

How to find the keys of duplicate entries in multidimensional array

I'm reporting on appointment activity and have included a function to export the raw data behind the KPIs. This raw data is stored as a CSV and I need to check for potentially duplicate consultations that have been entered.
Each row of data is assigned a unique visit ID based on the patients ID and the appointment ID. The raw data contains 30 columns of data, the duplicate check only needs to be performed on 7 of these. I have imported the CSV and created an array as below for first record and then append rest on.
$mds = array(
$unique_visit_id => array(
$appt_date,
$dob,
$site,
$CCG,
$GP,
$appt_type,
$treatment_scheme
)
);
What I need is to scan the $mds array and return an array containing just the $unique_visit_id for any duplicate arrays.
e.g. keys 1111, 2222 and 5555 all references arrays that contain the same value for all seven values, then I would need 2222 and 5555 returned.
I've tried search but not coming up with anything that is working.
Thanks
This is what I've gone with, still validating (data set is very big) but seems to be functioning as expected so far
$handle = fopen("../reports/mds_full_export.csv", "r");
$visits = array();
while($data = fgetcsv($handle,0,',','"') !== FALSE){
$key = $data['unique_visit_id'];
$value = $data['$appt_date'].$data['$dob'].$data['$site'].$data['$CCG'].$data['$GP'].$data['$appt_type'].$data['$treatment_scheme'];
$visits[$key] = $value;
}
$visits = asort($visits);
$previous = "";
$dupes = array();
foreach($visits as $id => $visit){
if(strcmp($previous, $visit) == 0){
$dupes[] = $id;
}
$previous = $visit;
}
return $dupes;

Check if multiple dates are the same in foreach

I have an "Events" table in MySQL :
EventsDate('id','event','start_date','end_date')
I'd like to check if multiple events have the same start date to show it differently in my HTML template.
My SQL request is :
SELECT * FROM EVENTSDATE where event='$id' and start_date>='$today' order by start_date asc
Now my foreach :
foreach ($upcomingDates as $value) { //$upcoming is the array with my sql request
}
How can I say : "if you find two rows with the same start_date, echo something"
I have a slightly different approach.
// Array to contain all values
$container = array();
// Loop through your existing array
foreach ($upcomingDates as $key => $value) {
// Check if the value is already in the container array
// If this is the case, its a duplicate.
if (array_key_exists($value['start_date'], $container)) {
$container[$value['start_date']]++;
echo $value.' is a duplicate with key '.$key;
}
// Add each value to the array
$container[$value['start_date']] = 1;
}
Another method is to use array_count_values()
foreach(array_count_values($upcomingDates) as $value => $c) {
if ($c > 1) {
echo $value.' is a duplicate';
}
}
Note that the second option won't work if your $upcomingDates is an array of arrays.
You can make an empty array before the for loop, and add each value in as a key. Then, on each iteration you can check that array for the key, like so:
$values = [];
foreach ($upcomingDates as $value) { //$upcoming is the array with my sql request
if(isset($values[$value])) //duplicate value found
//do something here
$values[$value] = 1;
}
Since you're ordering your events by start_date:
for ($i = 0, $length = count($upcomingDates); $i < $length; $i++) {
$date = $upcomingDates[$i];
if (isset($upcomingDates[$i + 1]) &&
$upcomingDates[$i + 1]['start_date'] == $date['state_date']) {
echo 'this and the next date are equal';
}
}
Try out GROUP BY
look here: GROUP BY
if you want to find duplicates, then you can directly get it from database
ex.
SELECT * FROM EVENTSDATE where event='$id' and start_date>='$today' GROUP BY start_date having count(start_date) > 1 order by start_date asc
or you can find duplicates from resulting array
return only duplicated entries from an array

check value for multiple array in loop

i have three array sure[],maybe[] and notify[] that are displaying in a loop like this:
sure[0] maybe[0] notify[0]
sure[1] maybe[1] notify[1]
sure[2] maybe[2] notify[2]
sure[3] maybe[3] notify[3]
And so on...
Now what I want that is in form post I get all arrays and there should be minimum one value of sure[0] or maybe[0] or notify[0] true or checked means horizontally`.
In this process will be same for all next rows and each row must contain minimum one true or checked value although can all selected or checked.
I am trying to solve this problem from past three days .
How can I do this please check it and give me idea.
thanks in advance
You can check whether at least one of the three is set by doing this:
$oneSet = $sure[0] || $maybe[0] || $notify[0];
If you want to do this in a loop, you can do something like this (assuming each list is equally long)
$oneSetInEach = true;
for( $i = 0 ; $i < count($sure) ; $i++ ) {
$thisSet = $sure[$i] || $maybe[$i] || $notify[$i]; // check if one is set here
$oneSetInEach = $oneSetInEach && $thisSet; // if all the previous ones are ok, and this is ok, we are still ok
}
// $oneSetInEach will now be true or false depending on whether each row has at least 1 element set.
If all array count() are same
<?php
$i = 0;
while ($i < count($sure)) {
if ((isset($sure[$i]) AND $sure[$i] == true) OR ( isset($maybe[$i]) AND $maybe[$i] == true) OR ( isset($notify[$i]) AND $notify[$i] == true)) {
// your code
}
$i++;
}
?>
Maybe:
$res = true;
for( $i=0 ; $i<count($sure) ; $i++ ) {
$res &= $sure[$i] || $maybe[$i] || $notify[$i];
}

Saving multiple HTML textareas in CodeIgniter

I would like to grab the values of several textarea fields and save them to the database. For now I have four of each with different values and I want to batch save these values, the textarea fields are:
<textarea name="compedia[]"></textarea>
<textarea name="specification[]"></textarea>
and the save function:
function saveCOA(){
$labref=$this->uri->segment(3);
$data= $this->input->post('compedia');
$data1= $this->input->post('specification');
$compedia=array(
'labref'=>$labref, //NDQA201303001
'compedia'=>$data,
'specification'=>$data1
);
foreach ($compedia as $value) {
$this->db->insert('coa_body',$value);
}
}
When I print_r($value) it returns :
NDQA201303001
Array ( [0] => Alphy [1] => poxy [2] => alphy [3] => poxy )
Array ( [0] => poxy [1] => alphy [2] => poxy [3] => alphy )
and when I try to save, it returns:
A Database Error Occurred
Error Number: 1054
Unknown column 'NDQA201303001' in 'field list'
INSERT INTO `coa_body` (`NDQA201303001`) VALUES ('')
Filename: C:\xampp\htdocs\NQCL\system\database\DB_driver.php
Line Number: 330
How should the syntax be so as to loop over all the textarea values and save them to the database at once?
I hope that
count($data) == count($data1); //Always True!
If that's the case the following will work:
for ($i=0;$i<count($data);$i++) {
$insert_data = array(
'labref'=>$labref, //NDQA201303001 - Same for all the rows
'compedia'=>$data[$i],
'specification'=>$data1[$i]
);
$this->db->insert('coa_body',$insert_data);
}
Check this Link: CodePad.org
Update:
Suggested by Rcpayan:
//This will reduce number of context switching,
//even though loping is doubled!
for ($i=0;$i<count($data);$i++) {
$insert_data[$i] = array(
'labref'=>$labref, //NDQA201303001
'compedia'=>$data[$i],
'specification'=>$data1[$i]
);
}
$this->db->insert_batch('coa_body',$insert_data);
You could do something like this, it's a bit longer but can also deal with compedia and specification not being equal. This solutions assumes a few things:
You want the value of labref to be the same for each row inserted
If the number of values for compedia and specification aren't equal, you still want to insert the row, but the 'missing' values will be set to NULL.
$labref = $this->uri->segment(3);
$compedia_data = $this->input->post('compedia');
$specification_data = $this->input->post('specification');
//Calculate which array is larger, so we can loop through all values
$max_array_size = max(count($compedia_data), count($specification_data));
//Iterate through the arrays
for ($i = 0; $i < $max_array_size; $i++)
{
$this->db->set('labref', $labref);
//If we still have a value(s) for compedia, then assign the value, otherwise set to NULL
if array_key_exists($i, $compedia_data)
{
$this->db->set('compedia', $compedia_data[$i]);
}
else
{
$this->db->set('compedia', NULL);
}
//If we still have a value(s) for specification, then assign the value, otherwise set to NULL
if array_key_exists($i, $specification_data)
{
$this->db->set('specification', $specification_data[$i]);
}
else
{
$this->db->set('specification', NULL);
}
//Insert into table: 'coa_body'
$this->db->insert('coa_body');
}
Alternatively, you could change the loop to assign the values to an array, then batch insert these values. This might offer better performance.
//Initial other relevant code is included in the example above (excluded here for brevity)
$insert_array = new array();
//Iterate through the arrays
for ($i = 0; $i < $max_array_size; $i++)
{
$row_array = new array();
$row_array['labref'] = $labref;
//If we still have a value(s) for compedia, then assign the value, otherwise set to NULL
if array_key_exists($i, $compedia_data)
{
$row_array['compedia'] = $compedia_data[$i];
}
else
{
$row_array['compedia'] = NULL;
}
//If we still have a value(s) for specification, then assign the value, otherwise set to NULL
if array_key_exists($i, $specification_data)
{
$row_array['specification'] = $specification_data[$i];
}
else
{
$row_array['specification'] = NULL;
}
//Add current row to the insert array, so it can be added to the database
$insert_array[$i] = $row_array;
}
//Insert into table: 'coa_body'
$this->db->insert_batch('coa_body', $insert_array);

Categories