Processing multidimensional csv-originated arrays in PHP - php

Within the first column of every row lies a position, i.e. Software Engineer, and if the user's position matches the one in that row, the nested for loop should check in each column of that row if the given id exists in the csv string for that column. I haven't worked much with arrays in PHP and most of my experience with multidimensional arrays lies within Java so pardon my java-themed PHP code:
$csv = read_csv('/filepath/tct.csv');
$csv_rows = 75;
for($i=1;$i<$csv_rows;$i++)
{
if(strtolower($user['user_pos']) == strtolower($csv[$i][0]))
{
for($j=1;j<sizeof($csv[$i]);j++)
{
if(array_search($user['id'], explode(",",$csv[$i][$j])))
{
return true;
}
}
}
}
Unfortunately, my java doesn't seem to work and all of the existing questions concerning PHP multidimensional arrays only confuse me with the $key->$value talk. Can anyone explain to me what I need to do adjust to get this to work?

So what I was doing is a perfectly acceptable (in terms of functionality) when processing multidimensional arrays, I just neglected to place the $ before j twice in the inner loop.
The most efficient and understandable way I've found thus far is:
foreach($csv as $csv_row) {
for($i=1;$i<count($csv_row);$i++) {
//do something with $csv_row[$i]
}
}
The standard-issue nested for loop is to ensure the row names aren't iterated over since I always had row names at column[0] (despite the fact that the outer foreach will loop over the column names in row 0)
Of course, this is heavily reliant on someone using the same spreadsheet/csv layout. If it's a csv of just data, I'm sure the inner loop could be changed to:
foreach($csv_row as $csv_col {
//do something with $csv_col
}

Related

for loop vs while loop vs foreach loop PHP

1st off I'm new to PHP. I have been using for loop,while loop,foreach loop in scripts. I wonder
which one is better for performance?
what's the criteria to select a loop?
which should be used when we loop inside another loop?
the code which I'm stuck with wondering which loop to be used.
for($i=0;$i<count($all);$i++)
{
//do some tasks here
for($j=0;$j<count($rows);$j++)
{
//do some other tasks here
}
}
It's pretty obvious that I can write the above code using while. Hope someone will help me out to figure out which loop should be better to be used.
which one is better for performance?
It doesn't matter.
what's the criteria to select a loop?
If you just need to walk through all the elements of an object or array, use foreach. Cases where you need for include
When you explicitly need to do things with the numeric index, for example:
when you need to use previous or next elements from within an iteration
when you need to change the counter during an iteration
foreach is much more convenient because it doesn't require you to set up the counting, and can work its way through any kind of member - be it object properties or associative array elements (which a for won't catch). It's usually best for readability.
which should be used when we loop inside another loop?
Both are fine; in your demo case, foreach is the simplest way to go.
which one is better for performance?
Who cares? It won't be significant. Ever. If these sorts of tiny optimizations mattered, you wouldn't be using PHP.
what's the criteria to select a loop?
Pick the one that's easiest to read and least likely to cause mistakes in the future. When you're looping through integers, for loops are great. When you're looping through a collection like an array, foreach is great, when you just need to loop until you're "done", while is great.
This may depend on stylistic rules too (for example, in Python you almost always want to use a foreach loop because that's "the way it's done in Python"). I'm not sure what the standard is in PHP though.
which should be used when we loop inside another loop?
Whichever loop type makes the most sense (see the answer above).
In your code, the for loop seems pretty natural to me, since you have a defined start and stop index.
Check http://www.phpbench.com/ for a good reference on some PHP benchmarks.
The for loop is usually pretty fast. Don't include your count($rows) or count($all) in the for itself, do it outside like so:
$count_all = count($all);
for($i=0;$i<$count_all;$i++)
{
// Code here
}
Placing the count($all) in the for loop makes it calculate this statement for each loop. Calculating the value first, and then using the calculation in the loop makes it only run once.
For performance it does not matter if you choose a for or a while loop, the number of iterations determine execution time.
If you know the number of iterations at forehand, choose a for loop. If you want to run and stop on a condition, use a while loop
for loop is more appropriate when you know in advance how many
iterations to perform
While loop is used in the opposite case(when you don't know how many
iterations are needed)
For-Each loop is best when you have to iterate over collections.
To the best of my knowledge, there is little to no performance difference between while loop and for loop i don't know about the for-each loop
Performance:
Easy enough to test. If you're doing something like machine learning or big data you should really look at something that's compiled or assembled and not interpreted though; if the cycles really matter. Here are some benchmarks between the various programming languages. It looks like do-while loop is the winner on my systems using PHP with these examples.
$my_var = "some random phrase";
function fortify($my_var){
for($x=0;isset($my_var[$x]);$x++){
echo $my_var[$x]." ";
}
}
function whilst($my_var){
$x=0;
while(isset($my_var[$x])){
echo $my_var[$x]." ";
$x++;
}
}
function dowhilst($my_var){
$x=0;
do {
echo $my_var[$x]." ";
$x++;
} while(isset($my_var[$x]));
}
function forstream(){
for($x=0;$x<1000001;$x++){
//simple reassignment
$v=$x;
}
return "For Count to $v completed";
}
function whilestream(){
$x=0;
while($x<1000001){
$v=$x;
$x++;
}
return "While Count to 1000000 completed";
}
function dowhilestream(){
$x=0;
do {
$v=$x;
$x++;
} while ($x<1000001);
return "Do while Count to 1000000 completed";
}
function dowhilestream2(){
$x=0;
do {
$v=$x;
$x++;
} while ($x!=1000001);
return "Do while Count to 1000000 completed";
}
$array = array(
//for the first 3, we're adding a space after every character.
'fortify'=>$my_var,
'whilst'=>$my_var,
'dowhilst'=>$my_var,
//for these we're simply counting to 1,000,000 from 0
//assigning the value of x to v
'forstream'=>'',
'whilestream'=>'',
'dowhilestream'=>'',
//notice how on this one the != operator is slower than
//the < operator
'dowhilestream2'=>''
);
function results($array){
foreach($array as $function=>$params){
if(empty($params)){
$time= microtime();
$results = call_user_func($function);
} elseif(!is_array($params)){
$time= microtime();
$results = call_user_func($function,$params);
} else {
$time= microtime();
$results = call_user_func_array($function,$params);
}
$total = number_format(microtime() - $time,10);
echo "<fieldset><legend>Result of <em>$function</em></legend>".PHP_EOL;
if(!empty($results)){
echo "<pre><code>".PHP_EOL;
var_dump($results);
echo PHP_EOL."</code></pre>".PHP_EOL;
}
echo "<p>Execution Time: $total</p></fieldset>".PHP_EOL;
}
}
results($array);
Criteria: while, for, and foreach are the major control structures most people use in PHP. do-while is faster than while in my tests, but largely underused in most PHP coding examples on the web.
for is count controlled, so it iterates a specific number of times; though it is slower in my own results than using a while for the same thing.
while is good when something might start out as false, so it can prevent something from ever running and wasting resources.
do-while at least once, and then until the condition returns false. It's a little faster than a while loop in my results, but it's going to run at least once.
foreach is good for iterating through an array or object. Even though you can loop through a string with a for statement using array syntax you can't use foreach to do it though in PHP.
Control Structure Nesting: It really depends on what you're doing to determine while control structure to use when nesting. In some cases like Object Oriented Programming you'll actually want to call functions that contain your control structures (individually) rather than using massive programs in procedural style that contain many nested controls. This can make it easier to read, debug, and instantiate.

Prefix filtering in php

How can I write a php program to find all arrays which share at least a single element in their prefixes. Let the prefixes are one fourth of the total elements in each array. Can anyone help me to code for that? I am a fresher in php. I need this to do a project regarding near duplicate detection.
You can use PHP's built in array function array_intersect
if(array_intersect($firstArray, $secondArray) == null)
{
//do not have any element common
}
else
{
//have at least one element common
}
you can create function of this code and pass all array's pairs to get result.

Initiating the same loop with either a while or foreach statement

I have code in php such as the following:
while($r = mysql_fetch_array($q))
{
// Do some stuff
}
where $q is a query retrieving a set of group members. However, certain groups have there members saved in memcached and that memcached value is stored in an array as $mem_entry. To run through that, I'd normally do the following
foreach($mem_entry as $k => $r)
{
// Do some stuff
}
Here's the problem. I don't want to have two blocks of identical code (the //do some stuff section) nested in two different loops just because in one case I have to use mysql for the loop and the other memcached. Is there some way to toggle starting off the loop with the while or foreach? In other words, if $mem_entry has a non-blank value, the first line of the loop will be foreach($mem_entry as $k => $r), or if it's empty, the first line of the loop will be while($r = mysql_fetch_array($q))
Edit
Well, pretty much a few seconds after I wrote this I ended up coming with the solution. Figure I'd leave this up for anyone else that might come upon this problem. I first set the value of $members to the memcached value. If that's blank, I run the mysql query and use a while loop to transfer all the records to an array called $members. I then initiate the loop using foreach($members as as $k => $r). Basically, I'm using a foreach loop everytime, but the value of $members is set differently based on whether or not a value for it exists in memcached.
Why not just refactor out doSomeStuff() as a function which gets called from within each loop. Yes, you'll need to see if this results in a performance hit, but unless that's significant, this is a simple approach to avoiding code repetition.
If there's a way to toggle as you suggest, I don't know of it.
Not the ideal solution but i will give you my 2 cents. The ideal would have been to call a function but if you dont want to do that then, you can try something like this:
if(!isset($mem_entry)){
$mem_entry = array();
while($r = mysql_fetch_array($q))
{
$mem_entry[] = $r;
}
}
The idea is to just use the foreach loop to do the actual work, if there is nothing in memcache then fill your mem_entry array with stuff from mysql and then feed it to your foreach loop.

Conditional of a loop within a loop is not matching

I have two databases, each containing email addresses of users. I've written a script that has the sole purpose of seeing which email addresses exist in both databases.
With that being said, please look at the following loops. Each loop contains hundreds of records (I've printed out the results from each as a verification). However, when the conditional finds a match, the conditional only matches against the email address from the first match. It remains "stuck" on the one record it matched from the initial query. In other words, if it matched on "test#test.com", then all future comparisons are against "test#test.com". It's almost like I need a "next()" method to move things along from the first array.
FWIW, I'm a complete PHP noob, so I'm sure there's something obvious I'm missing here.
while($member = mysql_fetch_array($members)){
while($emailAddress = mysql_fetch_array($emailAddresses)){
if ($member['email'] == $emailAddress['email']){
echo $member['email'] . "<br/>";
}
}
}
I think the problem is you looping through a mysql-result set, there's an internal data pointer that keeps sliding up 1 step at each loop.
Try putting the results in an array first.
$adresses = array();
while($emailAddress = mysql_fetch_array($emailAddresses)){
$adresses[] = $emailAddress['email'] ;
}
Then check your result within the array
while($member = mysql_fetch_array($members)){
if(in_array($member['email'], $adresses)){
echo $member['email'];
}
}
Or perhaps you can reset the datapointer after each loop, not sure if you can do this on mysql results but it works when looping through arrays.

PHP scope question

I'm trying to look through an array of records (staff members), in this loop, I call a function which returns another array of records (appointments for each staff member).
foreach($staffmembers as $staffmember)
{
$staffmember['appointments'] = get_staffmember_appointments_for_day($staffmember);
// print_r($staffmember['appointments'] works fine
}
This is working OK, however, later on in the script, I need to loop through the records again, this time making use of the appointment arrays, however they are unavailable.
foreach ($staffmembers as $staffmember)
{
//do some other stuff
//print_r($staffmember['appointments'] no longer does anything
}
Normally, I would perform the function from the first loop, within the second, however this loop is already nested within two others, which would cause the same sql query to be run 168 times.
Can anyone suggest a workaround?
Any advice would be greatly appreciated.
Thanks
foreach iterates over a copy of the array. If you want to change the value, you need to reference it:
foreach($staffmembers as &$staffmember) // <-- note the &
{
$staffmember['appointments'] = get_staffmember_appointments_for_day($staffmember);
// print_r($staffmember['appointments'] works fine
}
From the documentation:
Note: Unless the array is referenced, foreach operates on a copy of the specified array and not the array itself. foreach has some side effects on the array pointer. Don't rely on the array pointer during or after the foreach without resetting it.
and
As of PHP 5, you can easily modify array's elements by preceding $value with &. This will assign reference instead of copying the value.

Categories