I'm trying to sort data alphabetically by the COMPANY NAME from a flat file. I was thinking that a simple sort would handle this, but I was wrong. I now think that I need to use usort and cmp and then create another temp array. How can I accomplish this?
This is my current code.
$data_file = fopen($data_file_url, "r");
fgets($data_file); // IGNORE FIRST LINE IN FLATFILE - column names
while (!feof($data_file) ) {
$data_lines = fgets($data_file);
$data_ele = explode('|', $data_lines);
$company_name = $data_ele[0];
$section = $data_ele[1];
$category = $data_ele[2];
$service = $data_ele[3];
$service = substr_replace($service,"",-1); // trim last char
}
You should first store all elements in a big array and afterwards sort it using a callback:
$data_file = fopen($data_file_url, "r");
fgets($data_file); // IGNORE FIRST LINE IN FLATFILE - column names
$companies = array();
while (!feof($data_file) ) {
$data_lines = fgets($data_file);
$data_ele = explode('|', $data_lines);
$row = array();
$row['company_name'] = $data_ele[0];
$row['section'] = $data_ele[1];
$row['category'] = $data_ele[2];
$row['service'] = $data_ele[3];
$row['service'] = substr_replace($row['service'],"",-1); // trim last char
$companies[] = $row;
}
usort($companies, function ($a, $b) {
return strcmp($a['company_name'], $b['company_name']);
});
Please note: I'm using an anonymous function, introduced in PHP 5.3.0.
I would imporove upon Beats answer only by using the company name as a key in the array.
If you have multiple entries per company have a sub array.
By using the key as array it is already indexed when inserted.
I believe its faster.
You could also use fgetcsv here, which is also probably a little faster.
Related
PHP isn't returning unique items between assigned_IPs and IP_array.
I need an unique output.
I already tried merging arrays and comparing them.
$ips2 = array();
while ($row = mysql_fetch_assoc($result))
{
$ips2[] = $row["ipaddr"];
}
$assigned_ips = $ips2;
$ip_array = explode("\n",$ips);
$ips_left = array_diff($ip_array,$assigned_ips);
I need to return an unique array once PHP compares the 2 item lists.
Lucky for you, PHP has an array_unique() function for just such a purpose! You could perform it on both of the compared arrays before array_diff(), but I am pretty sure best (an most efficient) practice would be to perform it only once when you already have the results:
$ips2 = array();
while ($row = mysql_fetch_assoc($result))
{
$ips2[] = $row["ipaddr"];
}
$assigned_ips = $ips2;
$ip_array = explode("\n",$ips);
$ips_left = array_unique(
array_diff($ip_array,$assigned_ips)
);
Just for the sake of completeness, here is an alternative way that could be more efficient if you have a large number of duplicates that would bog down the array_diff() function:
$ips2 = array();
while ($row = mysql_fetch_assoc($result))
{
$ips2[] = $row["ipaddr"];
}
$assigned_ips = $ips2;
$ip_array = explode("\n",$ips);
$ips_left = array_diff(
array_unique($ip_array)
array_unique($assigned_ips)
);
I need to merge many arrays from a mysql DB I have. The amount of arrays can vary. I am serializing the data into the DB and unserializing it on the way out. Where I am stumped is trying to use array_merge but not sure how to get the data into it properly.
For instance I have
$sql_get_votes_data = "SELECT * FROM algo_users WHERE data LIKE '%$movie_id%'";
$result_get_votes_data = mysql_query($sql_get_votes_data);
$final_array = array();
while($row_get_votes_data = mysql_fetch_array($result_get_votes_data)) {
$final_array[] = unserialize($row_get_votes_data['data']);
}
Ultimately I need to be able to do a unique merge like this.
array_unique(array_merge($final_array1,$final_array2), SORT_REGULAR);
But since I have to place each array into a seperate variable in order to pass into array_merge I am not sure how to do that from the mysql call.
Any help would be awesome.
Why not merge every new array while you're still in your loop?
$mergedArray=array();
while($row_get_votes_data = mysql_fetch_array($result_get_votes_data)) {
$final_array = unserialize($row_get_votes_data['data']);
$mergedArray=array_merge($mergedArray,$final_array);
}
array_unique($mergedArray, SORT_REGULAR);
Or if you need to keep track of your individual arrays:
$mergedArray=array();
$i=0;
while($row_get_votes_data = mysql_fetch_array($result_get_votes_data)) {
$final_array[$i] = unserialize($row_get_votes_data['data']);
$mergedArray=array_merge($mergedArray,$final_array[$i]);
$i++
}
array_unique($mergedArray, SORT_REGULAR);
EDIT: I first understood you just wanted all arrays to be merged to a single array. The above edited answer now also removes duplicate entries as I now understand you wish.
You can e.g. use call_user_func_array for that.
<?php
$myarrs = array();
$result = call_user_func_array( 'array_merge', $myarrs); var_dump($result);
$myarrs[] = array(1,2,3);
$result = call_user_func_array( 'array_merge', $myarrs); var_dump($result);
$myarrs[] = array(4,5,6);
$result = call_user_func_array( 'array_merge', $myarrs); var_dump($result);
$myarrs[] = array(7,8,9);
$result = call_user_func_array( 'array_merge', $myarrs); var_dump($result);
but maybe it's more feasible to restructure the database and not to put the serialized arrays but single fields into the tables o the database can do the sorting/filtering/merging.
What would be a direct way to turn comma separated data from a mysql table, into a simple php array, other than doing it like I'm doing now?
I current do this in a very messy way by selecting data, then concatenating it into a string, which I later use.
I'm using PDO here.
Data is simple
locations
-------------------
US,UK,SE,DE
DE,SE,CA
GB,US,DE,SE
AU,NZ,GB
pdo
$d = $db->prepare('select locations a from destinations');
$d->execute();
$d->bindColumn('a',$a);
$count = $d->rowCount();
if($count >= 1) {
$b = '';
while($row = $d->fetch()) {
$b .= $a.',';
}
} else {
$b = 'No records to display';
}
echo $b;
The output I'm hoping to achieve is just a simple array like below, which is all the rows joined together.
Desired output
array('US','UK','SE','DE','DE','SE','CA','GB','US','DE','SE','AU','NZ','GB')
Can you help?
You're almost there. The easiest thing you can do is use explode(',', $b) for the complete string you have now, and frankly, I'm a bit surprised that you couldn't figure that part out after writing all that code.
Instead of concating everying in PHP, you can also concat it in the query using the GROUP_CONCAT function. This will introduce a limit, though, since the result of GROUP_CONCAT can be at most 32k, if I remember correctly.
Below is an alternative approach. Here, each row is fetched and exploded to an array immediately. That array is merged with (appended to, actually) to one big resulting array.
The advantage is that you are not concatting a big string first, which is relatively inefficient, but in practice, I doubt if you can tell the difference in performance.
$d = $db->prepare('select locations a from destinations');
$d->execute();
// An array for results.
$results = array();
$d->bindColumn('a',$a);
$count = $d->rowCount();
if($count >= 1) {
$b = '';
while($row = $d->fetch()) {
// explode each row and append it to the array.
$results = array_merge($results, explode(',', $a));
}
} else {
$b = 'No records to display';
}
// Display the complete array.
print_r($results);
You could just select the entries and then turn them into arrays by "exploding" them like this:
$locationArray = explode(",", $databaseEntry);
This will seperate your database entries by comma and add each entry to the array.
Documentation: http://php.net/manual/de/function.explode.php
Hope I could help
I'm creating a lottery to pair up people. So I want a way to shuffle the strings in an array where no item ends up on the same place. (You can't pair up with yourself)
public function shuffleSantas(){
$query = $this->db->get('person');
$givers = array();
$recievers = array();
foreach($query->result() as $row):
$givers[] = $row->name;
//here i want a random order, but no name can be on the same place as in $givers!
$recievers[] = '';
endforeach;
shuffle the array once and then pair up the first element with the second, the second with the third etc. and the last with the first.
$src = $query->result();
$givers = array();
$receivers = array();
foreach ($src as $idx=>$first_person){
$count = 0; //infinite loop guard
do{
++$count;
$sec_idx = rand(0,count($src)-1);
$second_person = $src[$sec_idx];
} while ($second_person==$first_person && $count<5);
$givers[] = $first_person;
$receivers[] = $second_person;
}
In this case one will be able to receive from one person and to give to other person. Is it OK? Also, this algorithm is not optimal and will definitely fall into infinity loop if there is only one person in an array.
If think there is no built-in function in PHP to shuffle that way. You have to write your own function.
Why does the operator
$array['country'][] return what logically would be $array[]['country']?
What I am saying is this. If you want to extract from a MySQL array, the value of ['country'] for every row, [1],[2]...[n], you have to use
$array['country'][]
despite fact that they are ordered as
$array['row#']['country']
Is this because PHP is reading something backwards, or because I am just lacking some fundamental array information?
FULL-ish code here
$result = array();
foreach($data as $value){
$array['country'][] = $value['country'];
$array['report'][] = $value['report'];
}
$data = $array;
Let me know if I am just dumb... I can't really grasp why this is working this way.
get an id from the db
SELECT id,country,report from yourdb
while ($row = mysql_fetch_array($result)) {
$array['country'][$row['id']] = $row['country'];
$array['report'][$row['id']] = $row['report'];
}
create an id
SELECT country,report from yourdb
$i=0
while ($row = mysql_fetch_array($result)) {
$array['country'][$i] = $row['country'];
$array['report'][$i] = $row['report'];
$i++
}
Why does the operator
$array['country'][]
return what
logically would be
$array[]['country']?
It is because you are constructing the array in that way:
If you use $array['country'][] = $value['country'];, you are adding a new value to the sub-array which is part of the containing array under the country key. So it will be mapped to $array['country'][], you cannot expect otherwise.
If you want it to map to array[]['country'], then (using part of code from
#Lawrence's answer), you'd have to add the new values using explicit numerical indexes as the key:
SELECT country,report from yourdb
$i=0;
while ($row = mysql_fetch_array($result)) {
$array[$i]['country'][] = $row['country'];
$array[$i]['report'][] = $row['report'];
$i++;
}
Assuming that $data has been built by you using a loop like what you pasted in the comments (while($row=mysql_fetch_assoc($result)){$data[]=$row;}) then my answer would be because that's exactly what you asked PHP to do.
The notion $data[] = some-value-here means take that value and add it with to the end of $data array with an auto-generated key I just don't care. That is, PHP will basically see what the last item's key is, add 1 and use that as the key for the item you are adding to the array.
So what you are doing with that loop is building an array whose keys are numbers starting from 0 and incrementing (+1 each cycle, this is the [] effect) and using these keys for the rows you are getting off the database result set.
If you want to access $data in the way you described, then you have to change the way you are building it. See Lawrence Cherone's answer for that.