Match substrings and only keep the highest value - php

I want to search an array for duplicate values in each subarray and if there is one, only keep the highest value connected to this item.
That's my question, but I love to add an example to clarify things!
This is my array:
Array
(
[0] => Array
(
[groupid] => 1
[points] => 5
)
[1] => Array
(
[groupid] => 1
[points] => 1
)
[2] => Array
(
[groupid] => 1
[points] => 4
)
[3] => Array
(
[groupid] => 2
[points] => 1
)
)
As you can see, the first three items have the same groupid. I want to match those items and see which of them has the highest points. The other one (with the lowest points) should be kicked out of the array.
So in this case, item 0, 1 and 2 are from the same group, but 2 has the highest points. 0 and 1 should be dropped out of the array.
My desired result would be something like this:
Array
(
[0] => Array
(
[groupid] => 1
[points] => 5
)
[1] => Array
(
[groupid] => 2
[points] => 1
)
)
I've been trying for a few hours now but no luck yet. Maybe I am overlooking something very simple and thinking to hard to figure this out... Any help would be appreciated!
EDIT
It's a Drupal site (but that shouldn't make any difference) and this is query:
foreach ($promotions as $value) {
$promo = db_query("SELECT * FROM {_promo_articles} WHERE art = :art AND promoid = :promoid", array(
':art' => $value['product'][0]->sku,
':promoid' => $value['promo_id'][0])) ->fetchAll();
}

As I see from your comment, the information is coming from the database so do something like this:
(pseudocode)
SELECT group_id, MAX(points)
FROM db_table
GROUP BY group_id;

I would do something like :
$final_array = array();
foreach($array AS $element)
{
if(!isset($final_array[$element["groupid"]]) ||
$final_array[$element["groupid"]] < $element["points"])
$final_array[$element["groupid"]] = $element["points"];
}
Then, $final_array would look like...
Array
(
[1] => 5
[2] => 1
)
(group 1 has 5 points, group 2 has 1 point)

You could use the usort function to order your array in order by points. This function will order it from greatest to least:
usort($myArray, function($a, $b) {
return $b['points'] - $a['points'];
});

As stated in comments the best way to do this is from your database if that is an option.
If not you can use array_reduce and a closure (PHP 5.3+)
$array = array_reduce($array,function(&$result, $val){
if (!array_key_exists($val["groupid"], $result){
$result[$val["groupid"]] = $val;
} else {
if ($result[$val["groupid"]]["points"] < $val["points"])
$result[$val["groupid"]]["points"] = $val["points"];
}
}, array());
Then if you want to reset the keys
$array = array_values($array);

Related

What is the way to mearge two arrays even duplicate values exists?

sele_itmid =
Array
(
[0] => 1
[1] => 1
[2] => 5
[3] => 6
)
$recp_qty =
Array
(
[0] => 4
[1] => 16
[2] => 1
[3] => 10
)
//when i tried using
$comine = array_combine($sele_itmid,$recp_qty);
print_r($comine);exit();
am getting a result like
Array
(
[1] => 16
[5] => 1
[6] => 10
)
what i actually want is
[1]=>4
[1] => 16
[5] => 1
[6] => 10
If possible some one Please explain why array_combine neglecting it!!
after getting an array what i actually want need to sum values of same keys
"why array_combine neglecting it?" - an array doesn't allow duplicate keys.
Here is a simple solution using array_map function (it will sum up the values of the same keys):
$result = [];
array_map(function($key, $b) use (&$result){
(isset($result[$key]))? $result[$key] += $b : $result[$key] = $b;
}, $sele_itmid, $recp_qty);
print_r($result);
The output:
Array
(
[1] => 20
[5] => 1
[6] => 10
)
Sounds as though you'd want to just map the two arrays together:
function sum($v1, $v2) {
return $v1 + $v2;
}
$result = array_map('sum', $sele_itmid, $recp_qty);
In here $sele_itmid 's values are used as the key of $comine array. Since an array can not have duplicate keys first value is rejected.

PHP Sort Multidimensional Array By Number Of Entries - If Equal Alphabetical

I have a multidimensional array, and I am trying to sort it so that the array with the most entries comes first, etc... Then if two arrays have the same number of entries, they should be arranged alphabetically. Also, if the entries could be sorted by the key, 'name', I think that would be great. As you can see below, I am using ldap_sort to sort by 'name'. But I'm sure calling too many sort functions is bad practice.
if ($conn == True ) {
Try {
// Authenticate
$bind = ldap_bind($conn, $user, $pass);
// Search AD
$search = ldap_search($conn, $dn, $filter, $attr);
// Sort
ldap_sort($conn, $search, 'name');
// Retrieve Data
$records = ldap_get_entries($conn, $search);
Foreach ($records as $record) {
if(is_array($record) && array_key_exists('l', $record)) {
$locations[$record['l'][0]][] = $record;
}
continue;
}
} finally {
// Close Connection
ldap_close($conn);
}
} else {
trigger_error('Unable_To_Connect_To_Server');
}
// Sort Location By Number Of Entries
array_multisort(array_map('count', $locations), SORT_DESC, $locations);
I guess to put it layman's terms.. Sorting entries alphabetically by their 'name' value, should be inherent. Then the arrays should be sorted by the number of entries, and if any arrays have the same number of entries they should be sorted alphabetically.
P.S. - I'm asking for help because it's hard for me to understand multidimensional arrays (especially those returned by ldap_search) and sorting them is even more mind-boggling to me.
EDIT Like I said, arrays confuse me but hopefully the below accurately depicts my intentions:
Array (
[Location1] => Array (
[0] => Array (
[l] => Array (
[count] => 1
[0] => Location1
)
[0] => l
[telephonenumber] => Array (
[count] => 1
[0] => XXX.XXX.XXXX
)
[1] => telephonenumber
[department] => Array (
[count] => 1
[0] => Department1
)
[2] => department
[name] => Array (
[count] => 1 [0] => User1
)
[3] => name
[ipphone] => Array (
[count] => 1
[0] => IPPhone1
)
[4] => ipphone
[mail] => Array (
[count] => 1
[0] => user#domain.com
)
[5] => mail
[count] => 6
[dn] => DistinguishedName1
)
)
)
I cut the above short (there are hundreds of records returned) and I'm not sure I ended it correctly. But I am essentially parsing the information to output something like below.
c_Location1
a_user1
b_user1
c_user1
a_Location2
a_user2
b_user2
b_location3
a_user3
b_user3
Write a function that compares the lengths of the arrays. If they're the same, it compares the name entries. Use that as the callback function for usort.
usort($records, function($x, $y) {
if (count($x) == count($y)) {
$u1 = $x['name'][0];
$u2 = $y['name'][0];
return $u1 < $u2 ? -1 :
($u1 > $u2 ? 1 : 0);
} else {
return count($y) - count($x);
}
});

Update an array with fields from matching array

I have Array1 that pulls all of the entries for a Wordpress custom post type, and I have Array2 from another table that shows if that post type has been seen by a specific user. If the ID of Array1 & the PageID of Array2 are the same, then add the [Started] & [Finished] fields from Array2 to Array1. Basically I want to combine them to form Array3. I have tried many different solutions with array_combine but can't get the result I'm looking for.
Array1 (
[0] => stdClass Object ( [ID] => 75 [post_title] => Test Training Video )
[1] => stdClass Object ( [ID] => 80 [post_title] => Test 2 )
[2] => stdClass Object ( [ID] => 85 [post_title] => Test 2 ) )
Array2 (
[0] => stdClass Object ( [PageID] => 75 [Started] => 1 [Finished] => 1 )
[0] => stdClass Object ( [PageID] => 80 [Started] => 1 [Finished] => 0 ) )
Array3 (
[0] => stdClass Object ( [ID] => 75 [post_title] => Test Training Video [Started] => 1 [Finished] => 1 )
[1] => stdClass Object ( [ID] => 80 [post_title] => Test 2 [Started] => 1 [Finished] => 0 )
[2] => stdClass Object ( [ID] => 85 [post_title] => Test 2 ) )
Something like this?
$array3 = array();
foreach( $array1 as $arr1 )
{
foreach( $array2 as $arr2 )
{
if( $arr1["ID"] == $arr2["PageID"] )
{
$array3[] = array( $arr1["Started"], $arr2["Finished"] );
}
}
}
array_combine() is not the right function for this.
In your case, you need to use a foreach-loop to loop over the values of your first array and compare them with your second array.
You also need to rearrange array 2, so that you can easily access the values for started and finished using the pageID as key:
$pageMap = array();
foreach($array2 as $entry) {
$pageMap[$entry['PageID']] = array('started' => $entry['Started'], 'finished' => $entry['Finished']);
}
Then you can do:
$combined_array = array();
foreach($array1 as $post) {
if(!isset($pageMap[$post['ID']])) continue; // do nothing if there are no started/finished entries.
$combined_array[$post['ID']] = array_merge($post, $pageMap[$post['ID']]);
}
You could try a first loop to make your array "ID" match and then combine both arrays
foreach( $array2 as $key=>$value )
{
$value['ID'] = $value['PageId'];
unset($value['PageId']);
$array2[$key] = $value;
}
$array3 = array_merge_recursive($array1,$array2);
After trying the posted solutions I decided to make the change in my $wpdb->get_results sql statement instead of using 2 different sql statements and then combining the 2 different arrays. With help from this post - SQL query to join two tables despite the other table may not have values, I was able to use the following to get the desired result.
$oneBigQuery = $wpdb->get_results("SELECT a.ID, a.post_title, b.PageID, b.Started, b.Finished
FROM $wpdb->posts AS a
LEFT JOIN exampleTableName AS b
ON a.ID = b.PageID
AND b.UserID = 3
WHERE a.post_type = 'custom-post-type'
");

Sorting in php Arrayss

My sql table consists of ID,Book name,Genre and ratings.Currently my array from my sql table looks like this (output)
Array (
[book] => Array (
[0] => Array
( [0] => 1
[1] => book one
[2] => Fantasy/Horror
[4] => 8.9 )
[1] => Array (
[0] => 2
[1] => book two
[2] => Comedy
[4] => 8.3 ) ) )
i want to sort this array to DESC by ID
Also in the future by title.
The array variable is $book so i wrote ksort($book) also tried arsort
for some reason it doesnt work? Is it because of the array? Thanks!
IF you are able to:
Use SQL sorting instead, because of the speed and flexibility (Use db-engine where it's appropiate) Only use array-functionality if you really need to! :-)
Do something like:
SELECT ID,Book name,Genre, ratings ORDER BY ID DESC
OR
If you have still have to use array sorting, use usort() in PHP:
<?php
//Book array
$bookArray['book'][0] = array(2, 'book one', 'Fantasy/Horror', 8.9);
$bookArray['book'][1] = array(1, 'book two ', 'Comedy', 8.3);
function sortByIndex($a, $b) {
return $a[0] - $b[0];
}
usort($bookArray['book'], 'sortByIndex');
echo 'RESULT=' . print_r($bookArray,true);
?>
Results in this output:
RESULT=Array ( [book] => Array ( [0] => Array ( [0] => 1 [1] => book two [2] => Comedy [3] => 8.3 ) [1] => Array ( [0] => 2 [1] => book one [2] => Fantasy/Horror [3] => 8.9 ) ) )
Book two comes first here, because in my example I set the first index to be 1 with value 'book two'.
The easiest way is to add this to your SQL statement at the end:
ORDER BY id DESC
Also if you really want to know how to do it in PHP you would do it this way:
function cmp($a, $b)
{
if ($a[0] == $b[0]) {
return 0;
}
return ($a[0] > $b[0]) ? -1 : 1;
}
usort($array['book'], "cmp");
Just you need to change your Select Statement. It should be something like this -
select id,bookname,genre,ratings from yourtable ORDER BY id DESC,bookname;

PHP array sorting by scored results from database

I have an array that I'm simply trying to order by a score key that contains the value that I'm trying to sort by. The desired results would change the order of the array below to display the index in the following order: [0], [2], [1].
I'm looping through the results which are pulled from a database. I'm creating a key named score and then pushing the $row2 array in to a separate array because if I use mysql_data_seek it gets rid of the score key.
Also it's creating an unwanted key score at the bottom.
How can I best clean this up and make sure the results are ordered high to low as desired?
$my_array = array();
while ($row2 = mysql_fetch_assoc($result2))
{
//score determined here
//$row2['score'] = ...more math, variable is numeric, not a string
array_push($array_page,$row2);
}
Current undesired results...
Array
(
[0] => Array
(
[score] => 7
)
[1] => Array
(
[score] => 2
)
[2] => Array
(
[score] => 4
)
[score] =>
)
Desired results...
Array
(
[0] => Array
(
[score] => 7
)
[2] => Array
(
[score] => 4
)
[1] => Array
(
[score] => 2
)
)
function scoreSort($a, $b){
if($a['score'] == $b['score']) return 0;
return $a['score'] > $b['score'] ? -1 : 1;
}
usort(&$myArray, 'scoreSort');
on php>5.3 you can use inline-functoins:
usort(&$myArray, function($a,$b){ /* ... */ });

Categories