Find partial string inside array - php

I have this array from an AJAX request:
array (
[0] => 'lat,long#id_1'
[1] => 'lat,long#id_2'
[2] => 'lat,long#id_3'
)
The problem here is I'm not gonna have always a 'correct-ordered' array like that, so it may look like this one:
array (
[0] => 'lat,long#id_1'
[1] => 'lat,long#id_2'
[2] => 'lat,long#id_3'
[3] => 'lat,long#id_1'
[4] => 'lat,long#id_3'
[5] => 'lat,long#id_2'
)
I need to get the last array value of every id_X (currently only 3 ids):
array (
[3] => 'lat,long#id_1'
[4] => 'lat,long#id_3'
[5] => 'lat,long#id_2'
)
How can I find each last value of that array based on partial string (id_X)?

First do a reverse sort to ensure the latest values are parsed first. Then run them through a loop, matching the partial string to get the ID, adding the data to an array if the ID index doesn't exist yet. Last values will be added to your array, others will be neglected. Something like this:
rsort($ajaxy);
$lasts = [];
foreach($ajaxy as $str) {
$id = substr($str, strrpos($str, '#') + 1);
if (!isset($lasts[$id])) {
$lasts[$id] = $str;
}
}
var_dump($lasts);
If you have a huge array, and you know the amount of IDs you will be getting, you can add in a check to terminate the loop when all required IDs have been added in to avoid redundant processing.
Otherwise, don't bother with the reverse sort, and simply keep overwriting previous values 'til the end, but I find this a cleaner approach. ^_^

Related

Find the maximum and parent value in an array

I searched many thread but i can't find this solution
I have this Array
Array
( [0] => [1] => Array ( [0] => 2019-01-11T23:30:00CET [1] => -12.6 ) [2] => [3] => Array ( [0] => 2019-01-11T23:20:00CET [1] => -12.5 ) [4] => [5] => Array ( [0] => 2019-01-11T23:10:00CET [1] => -12.6 ) [10] => [11] => Array ( [0] => 2019-01-11T22:40:00CET [1] => -12.4 )
I found the path to have the maximum or minimum value ( Column [1] ) from this Array but i need to find the relative Parent
(example the minimum -12.6 is in the [1][0] as 2019-01-11T22:20:00CET)
of this two values that are show in the first column ( Column[0] )
Thanks
If you use array_column() to extract the second column of your data, then you can use min() or max() with that array to pick which one you want. This code then extracts the ones that match using a foreach() and if to check if it matches (not exactly sure what you want as output, but this should help)...
$source = [["2019-01-11T23:30:00CET", -12.6],
["2019-01-11T23:20:00CET", -12.5],
["2019-01-11T23:10:00CET", -12.6]
];
$extract = min(array_column($source, 1)); // or use max()
$output = [];
foreach ($source as $key => $element) {
if ( $element[1] == $extract ) {
// Matches, so add to output
$output[$key] = $element[0];
}
}
print_r($output);
will give
Array
(
[0] => 2019-01-11T23:30:00CET
[2] => 2019-01-11T23:10:00CET
)
You could use array_filter() to extract the matching rows, but a foreach() is enough for a straightforward thing like this (IMHO).
If there is a possibility of blank values or strings in the value column, this may confuse the min() as it will consider the values and compare them as strings, to ensure they are all compared as numbers you can add...
$values = array_map("floatval", array_column($source, 1));
$extract = min($values); // or use max()
The array_map("floatval",... goes through the list and converts them all to float values.
Also, here's a generalized algorithm-sketch for "finding the max in some array", expressed as pseudo-code:
"Leave quietly" if the array is empty, or throw an exception.
Otherwise, assume that the first element in the array is the biggest one.
Now, loop through the remaining elements, testing if each one is, in fact, bigger than the "biggest one" that you have so far. If so, select it as the "biggest."
When the loop is finished, return your answer.
Now – this is what a geek would call "an O(n) algorithm," which is to say that its execution-time will be "on the order of" the number of elements in the array. Well, if this is a "one-off" requirement, that's fine. Whereas if what you actually want to do is to get "more than one" max-element, sorting the array (once, then holding on to the sorted result ...) becomes significantly better, because the sort is going to be O(log(n)) ... "on the order of some logarithm of the number of elements," ... and the subsequent cost of "popping off" elements from that sorted array becomes non-existent.
There are other ways to do it, of course – trees and such - but I've already blathered-on too long here.

Comparing arrays until I have a unique array

I have the following multidimensional array called $existing_combinations
Array
(
[0] => Array
(
[1] => 6
[2] => 7
[3] => 9
)
[1] => Array
(
[1] => 1
[2] => 21
[3] => 9
)
[2] => Array
(
[1] => 1
[2] => 7
[3] => 9
)
)
I then generate a new array ($new_combination) which has a combination of the same set of values. Example:
Array
(
[1] => 6
[2] => 21
[3] => 9
)
I then test if $new_combination exists in $existing_combinations with the following in the hope that I will end with a unique combination in $new_combination:
foreach($existing_combinations as $key => $combination){
while($new_combination == $combination){
$new_combination = generateNewCombination();
}
}
The problem is that if $new_combination matches an array that is not at index 0, then when I generate a new combination I am at risk of this matching a $combination that has already been tested against (and will not be tested again).
Sorry if this is a simple one but I'm struggling to think of how I can ensure $new_combination will always end up unique.
Any ideas?
Thanks
You can use in_array in this case, because php compares arrays as value. So, the code can be:
while(in_array($new_combination = generateNewCombination(), $existing_combinations));
print_r($new_combination);
I wrote the below before realizing that in_array can also see if an array exists within an array. So you can simply do this:
if (!in_array($new_combination, $existing_combinations)) {
// It's unique.
}
In the below outdated bit, see the note on using sort, if a different sequence of the same numbers isn't considered unique for your purposes.
[ For Entertainment ]
May not be the most elegant way around, but I would simply do this to keep it simple:
$combo_hashes = [];
// Implode the existing combos into strings.
foreach($existing as $vals) {
$combo_hashes[] = implode(':', $vals);
}
Then, all you need to check with your new combo is:
// Check if the "hash"-string already exists.
if (!in_array( implode(':', $new_combo), $combo_hashes)) {
// ... and we're unique.
}
This presumes that you consider [1,3,2] different from [2,1,3]. If they are equivalent (I don't know what your use case is), you should sort($vals); before you generate the check-strings.
Merge all the second level arrays and run array_unique() to get rid of the duplicate values.

Foreach and unset()

Ran into a little snag and wondering if there is a "best practices" way around it.
So I just learned that "A php foreach will execute on the entire array regardless. Test unsetting a value that is next in iteration. It will iterate on the offset, but the value will be null. – Kevin Peno Dec 22 '09 at 21:31" from How do you remove an array element in a foreach loop?
It's the first part of that that is messing with me. I'm iterating through an array with foreach. It's a search function so I'm removing the element I just searched for, so when the loop runs again its minus that element.
I do NOT want to reindex if at all possible, although if I have to I can.
Array
(
[0] => Array
(
[0] => a
[1] => aa
[2] => aaa
)
[1] => Array
(
[0] => b
[1] => bb
[2] => bbb
)
[2] => Array
(
[0] => c
[1] => cc
[2] => ccc
)
[3] => Array
(
[0] => d
[1] => dd
[2] => ddd
)
)
foreach($array as $key=>$value) {
$searchresult[] = search function returns various other keys from array
foreach($searchresult as $deletionid) {
unset($array[$deletionid]);
}
}
So on the first iteration it uses $array[0] obviously but the $searchresults might return 4,5,6,7. So those keys are removed from $array.
Yet the foreach loop still iterates through those and gives me back a bunch of empty arrays.
I did read How does PHP 'foreach' actually work? and I get some of it.
Thanks
In my opinion, the best way to remove array elements based on indexes is to use the array_* set of functions, like array_diff and array_intersect (or array_diff_key and array_intersect_key in your situation).
$indexes_to_remove = array(2,3,4);
$indexes_to_remove = array_flip($indexes_to_remove);
$array = array_diff_key($array,$indexes_to_remove);
If the array is guaranteed to be exhausted at some point, you can use this:
while (true) {
$searchresult[] = search function returns various other keys from array
foreach($searchresult as $deletionid) {
unset($array[$deletionid]);
}
if (count($array) === 0) {
break;
}
}
And yes I know while (true) is pretty evil, but I find in cases like these it does exactly what is needed.
If you want to prevent it from infinite looping you could always add a variable, increment each iteration, and break when it reaches a high value that should never happen (like 10 * count($array))

manipulate multiarrays

I am pulling some data from a mysql table via the following:
$result = mysql_query("SELECT characters_ID, name, borndate, deathdate, marrieddate, ispregnant FROM characters WHERE isfemale='1'",$db);
$femaledata = array();
while ($row_user = mysql_fetch_assoc($result))
$femaledata[] = $row_user;
This gives me an array that looks like this:
Array (
[0] => Array ( [characters_ID] => 2 [name] => Helene [borndate] => 35 [deathdate] => 431 [marrieddate] => 157 [ispregnant] => 0 )
[1] => Array ( [characters_ID] => 4 [name] => Isabelle [borndate] => 161 [deathdate] => [marrieddate] => 303 [ispregnant] => 1 )
[2] => Array ( [characters_ID] => 7 [name] => Helene [borndate] => 326 [deathdate] => [marrieddate] => [ispregnant] => 0 )
[3] => Array ( [characters_ID] => 72 [name] => Faylinn [borndate] => 335 [deathdate] => [marrieddate] => [ispregnant] => 0 )
[4] => Array ( [characters_ID] => 74 [name] => Relina [borndate] => 349 [deathdate] => [marrieddate] => [ispregnant] => 0 )
)
Now I need to remove any characters who have a value for deathdate or ispregnant, and then I need to run some code on the others. For instance I need to grab the borndate value, compare it to the current date to find age, and based partly on age, I need to run code for each to determine if the character has become pregnant on the turn.
Apologies that this seems like a long-reaching question. Multidimensional arrays still seem to confound me.
Edit: (question needs to be more clear)
Can you please suggest the best way that I would either explode or break up the array, and then do conditional modification to the data, or instead how I could remove unneeded data and then do conditional modification to the data.
My ultimate output here would be taking suitable female characters (not dead or pregnant already), and based on their age, giving them a chance at becoming pregnant. If true, I'd throw some code back at the SQL database to update that character.
Thanks!
All the things you need could probably get done with SQL :
Now I need to remove any characters who have a value for deathdate or
ispregnant
Simply add some argument to your WHERE condition :
isPregnant IS NULL AND deathdate IS NULL
For instance I need to grab the borndate value, compare it to the
current date to find age
Depending of your field format the maths could be done in SQL , have look to the DATE function of mysql
Don't underestimate the power of your sql server , 99% of the time it is probably faster than php to work on data set.
Instead if immediately removing some rows from your array, try limiting the data you recieve through SQL.
You can loop through your array like this:
foreach($femaledata as $female)
{
echo $female['name'];
}
do you mean something like this?
$femaledata = array();
while ($row_user = mysql_fetch_assoc($result)) {
$ok = false;
// do you validation for every user
if($ok) array_push($femaledata,$row_user);
}
TJHeuvel gave you the right answer, and you should accept that answer. However, to inform: multidimensional arrays need not confound. Let me see if I can explain.
In PHP, you can put any object at all into an array, including other arrays. So, let's say you have an array that contains other arrays. When you iterate over that array using a looping construct (usually a foreach loop), each iteration of the loop will give you another array; if you want to access the elements of this sub-array, just loop over it. This is called a nested loop. Example:
$r = array(
array(1,2,3),
array(4,5,6),
array(7,8,9)
);
foreach ($r as $cur) {
foreach ($cur as $num) {
echo $num;
}
}
In each iteration of the outer loop, $cur contains an array; the inner loop iterates over contents of this array. This technique allows you to process arrays of any dimension.
However, in your specific case, you don't need to use an inner loop to iterate over your subarrays. You only need to access certain elements of your subarrays by their keys, rather that processing all of them in turn. So, a simple foreach loop will do.

Remove items from array with value above/below threshold

What's the most efficient way to remove items from an array in php where the value is greater than a pre-determined threshold, e.g. given an array
Array
(
[0] => 1.639
[1] => 2.168
[4] => 1.897
[6] => 4.129
)
I would like to remove all the items with a value greater than e.g. 2, preserving key associations, to give
Array
(
[0] => 1.639
[4] => 1.897
)
I know I can do this using a foreach() loop but it seems that there should be a more elegant way.
No matter what you use, the array has to be looped through but you can hide it by using array_filter:
function test($var) { return $var < 2; }
$data = array_filter($data, 'test');

Categories