sorting simple_html_dom arrays - php

I have been trying to get this to work for a while now!
What I am trying to do is sort two arrays, so they both get ordered depending on the values inside one of the arrays. I don't know how to "attach" the arrays so both get ordered.
Here is my code:
$html = file_get_html('http://www.amazon.co.uk/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=hat&x=0&y=0');
$test = strtolower("Beechfield Turn-up Beanie");
$arrayT = array();
$arrayP = array();
foreach ($html->find('div.product') as $results) {
foreach ($results->find('a.title') as $title) {
$titleLow = strtolower($title->plaintext);
similar_text($test, $titleLow, $percent);
$arrayT[] = $title->plaintext;
$arrayP[] = round($percent);
}
}
I am comparing how similar the titles brought back from the outside website are to the variable $test, which in this case is just an example.
Next I want my output to be sorted depending on the $percent variables. For example with no sorting the output would be:
title-1 55
title-2 90
title-3 66
However I want it to be sorted:
title-2 90
title-3 66
title-1 55
I have tried using array_multisort however it would only sort each array independently. I have had a look at usort and ksort as well but couldn't get a working answer.
Any help would be appreciated! I have never used any kind of sorting in PHP and have only started learning arrays so please go easy on me.

I would suggest you to do this:
Instead of storing title and percentage in two different array.
you can have array indices as the titles.
Like this:
$html = file_get_html('http://www.amazon.co.uk/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=hat&x=0&y=0');
$test = strtolower("Beechfield Turn-up Beanie");
$arrayTP = array();
foreach ($html->find('div.product') as $results) {
foreach ($results->find('a.title') as $title) {
$titleLow = strtolower($title->plaintext);
similar_text($one, $titleLow, $percent);
$arrayTP[$title->plaintext] = round($percent);
}
}
You can sort it later using an array sort function based on the percentage. Use this: asort.
Because:
This function sorts an array such that array indices maintain their correlation with the array elements they are associated with. This is used mainly when sorting associative arrays where the actual element order is significant.
For printing do this:
foreach($arrayTP as $title => $percent ) {
.
.
.

Related

Breaking a MultiDimensional Array into a Single Dimension

I have fields in mySQL which is currently being stored like this under the field "tags"
Shopping|Health & Beauty
Coffee|Shopping
What I'm trying to do is to loop through this to create a single dimension array and to grab only the unique values.
I have my query selecting DISTINCT tags from TABLE and run the loop like this:
while ($row_tags = mysql_fetch_assoc($r_tags)) {
$tags = $row_tags['tags'];
$imploded_tags[] = explode("|",$tags);
}
echo "<pre>";
print_r($imploded_tags);
The result from the print_r is showing it as a multidimensional array. I've tried to reexplode it and implode it in different ways, but I haven't been able to get any success. Is there a way that I can create this into a single dimension array? Not all tags will have an equal amount of tags separated by |, so I can't seem to get it to go with a function that I tried from another StackOverflow post. Any help would be greatly appreciated!
OUTPUT:
Array
(
[0] => Array
(
[0] => Shopping
[1] => Health & Beauty
)
[1] => Array
(
[0] => Coffee
[1] => Shopping
)
try this
while ($row_tags = mysql_fetch_assoc($r_tags)) {
$tags = $row_tags['tags'];
$tags = explode("|",$tags);
foreach($tags as $v){
$imploded_tags[] = $v;
}
}
I would do something like:
$imploded_tags = array_merge(explode("|",$tags), $imploded_tags);
}
$imploded_tags = array_unique($imploded_tags);
echo "<pre>";
print_r($imploded_tags);
See the manual on array_merge and array_unique.
However, I do think you are not using the right way to store your tags; they should be stored in a separate table as separate values.
What's going on is when you're fetching your rows from MySQL, you're essentially getting a bunch of data in an array in the first place, which is why you have to loop through them.
With your your implode function, you're taking a bunch of strings, then getting another array set and then appending that to an external array.
If you really wanted to get a single dimensional array without having this multidimensional thing going on, all you really need to do is utilize another loop within that loop.
$all_tags = array();
while ($row_tags = mysql_fetch_assoc($r_tags)) {
$tags = $row_tags['tags'];
$imploded_tags[] = explode("|",$tags);
for($i = 0; $i < count($imploded_tags); $i++) {
$all_tags[] = $imploded_tags[$i]
}
}
print_r($all_tags);

Convert foreach to for in PHP

foreach ( $this->parent->get_sections(null, $this->parent->author) as $section)
{
//...
}
I'm trying to do is force the loop to output each $section in the order I want. Each $section's name can be retrieved by $section->name. Let's say that I want to output $section "Section 2" first and then "Section 1" (and not in the order of the foreach). How can I force it do that? I presume the proper way would be a for loop with an if checking section names each time.
The proper way would be sorting the results when you call parent->get_sections(). How you would do this is entirely up to the implementation of that class and method. Changing this foreach to for for the sake of sorting seems like a code smell to me.
For the sake of answering the question as technical as possible.
$sections = $this->parent->get_sections(null, $this->parent->author);
$num_sections = count($sections);
for ($i = 0; $i < $num_sections; $i++) {
// what you do here is up to you $sections[$i]
}
Especially if you are not aware of the specific number of sections, you could use usort() to do a dynamic custom sort on the get_sections()-returned array or object and then utilize the existing code. (This is a little more elegant, imo, than doing the same in a for/foreach loop).
Not knowing the structure of your code, I would do something like.
// Get Org Sections
$sections = $this->parent->get_sections(null, $this->parent->author);
// Loop thru sections to get an array of names
foreach ( $sections as $key=>$section)
{
$sorted_sections[$section->name] = $key;
}
// Sort Array
//ksort — Sort an array by key
//krsort — Sort an array by key in reverse order
krsort($sorted_sections);
foreach ( $sorted_sections as $section)
{
// Orig Code
}
$section = $this->parent->get_sections(null, $this->parent->author);
echo $section[2]->name;
echo $section[1]->name;//just output the indexes the way you want
if you want it sorted, in say descending order, you can sort it that way and then use a for loop to display.

shuffle() everything in array?

I'm using shuffle() to randomly generate items on my site like so:
shuffle($items);
$shirts = array();
foreach ($items as $key => &$row) {
$shirts[$row['Id']] = $row['shirts'];
}
The code goes further, but basically it's running a foreach and displays 12 results. However, shuffle() seems to only return the first 12 items in the array and shuffle them. The array may contain dozens of items, and I want to shuffle through the entire array. What am I doing wrong?
We need to see more code. As of right now according to the code, it should display every result (not just 12). This must mean that you're cutting the array down to 12 before you even shuffle it.
I just wrote this function to shuffle an array. It return the array shuffled so you can still keep the original array:
`function lowellshuffle($unshuff) {
$co = count($unshuff);
$m=0;
for ($i=0;$i<$co;$i++){
$p = rand(0,count($unshuff)-1);
$shuffled[$i] = $unshuff[$p];
for ($j=0;$j<count($unshuff);$j++){
if ($unshuff[$j] !== $shuffled[$i]){
$nq[$j- $m] = $unshuff[$j];
}
else {$m++;}
}
unset($unshuff);
$unshuff = $nq;
unset($nq);
$m=0;
}
return $shuffled;
}`

PHP Typecasting an Int as a String - doesn't seem to work as expected

I am trying to calculate percentiles for users in a database. In order to do this I have a $data array that I need to sort.
I have a query object that contains User_ID, Total_User_Orders, and Total_Orders. Here's how the code looks so far:
// Loop through the users
foreach($query->result() as $row)
{
(string)$user_id = (string)$row->user_id;
$data[$user_id] = number_format((($row->total_user_orders/$row->total_orders)*100), 5);
}
// Sort the $data array
array_multisort($data);
print_r($data);
What (I believe) that should do is typecast $row->user_id (an int) as a string. Then, the $data[$user_id] index should be set as a string - right...?
When I sort the array using array_multisort it sorts it as though the index was an Integer, rather than a String. This means it loses the index.
The PHP manual for array_multisort() states, "Associative (string) keys will be maintained, but numeric keys will be re-indexed.". I have also tried using array_multisort($data, SORT_STRING), but the same output occurs. However - it does work when I do $data['#'.$user_id], but this doesn't quite feel like the right solution to me!
Can anyone help? Thanks in advance!
I think you're overcomplicating things. With no testing, I'd think indexing the $data-array like this would work:
$data[(string)$row->user_id] = ...
or
$data[''.$user_id] = ...
EDIT:
Otherwise you could build your array multi-dimensional and sort by one of the indices, like this:
foreach($query->result() as $row) {
$data[] = array(
'user_id' => $row->user_id,
'percent' => number_format((($row->total_user_orders/$row->total_orders)*100), 5);
);
}
Or you could index by the percentage and sort by the keys (using ksort()):
foreach($query->result() as $row) {
$data[number_format((($row->total_user_orders/$row->total_orders)*100), 5)] = $row->user_id];
}
The last solution could be dangerous if several users have the same percentage.
Personally I would probably go with the asort() solution mentioned above.
As described in my comment, array_multisort() is not what you are after here. You don't have multiple arrays or a multi-dimensional array.
To maintain the key => value association in the array and sort the contents use asort().
foreach ($query->result() as $row) {
$percent = ($row->total_user_orders / $row->total_orders) * 100;
$data[$row->user_id] = number_format($percent, 5);
}
asort($data);
If you want descending percentages reverse the array after it's been sorted.
$data = array_reverse($data, true);

PHP retrieve array of items from a multidimensional array without looping?

I have a large array of arrays and each of these sub-arrays has an ID and some other info. Is there a way to access an array of just the ID's without using a loop?
Sort of like
$array[ALLOFTHEITEMS][Id];
I want to eventually compare these ID's to another flat array of ID's.
I would usually do a for loop and then just add the id of each item to a new array and then compare them. But is there a faster way?
Not sure if its faster then foreach as I've never benchmarked it but an alternative to foreach would be:
php 5.3
$ids = array_map(function($data) { return $data['id']; }, $array);
php < 5.3
function reduceToIds($data) {
return $data['id'];
}
$ids = array_map('reduceToIds', $array);
I normally use the foreach approach myself though.

Categories