Position of Max value in Array PHP - php

Hey guys,
so I have two arrays
$names = array('jimmy', 'johnny', 'sarah');
$ages= array('16', '18', '12');
I am trying to find the biggest/maximum value in ages, get that elements position and use said position to get the corresponding name. How would I achieve this?
Is there a better way to achieve the corresponding name, perhaps bundling all in one?
Thanks

This should get the key for you:
$names = array('jimmy', 'johnny', 'sarah');
$ages= array('16', '18', '12');
$oldest = array_search(max($ages), $ages);
echo $names[$oldest];
You should note though, that if two persons would have the same age, the first of these two persons would be the one returned.
if you need to find all the oldest you should use array_keys() instead of array_search() like this:
$names = array('jimmy', 'johnny', 'sarah', 'kristine');
$ages = array('16', '18', '12', '18');
$oldestPersons = array_keys($ages, max($ages));
foreach($oldestPersons as $key) {
echo $names[$key].'<br />';
}

$oldest_key = 0;
$age_var = 0;
foreach ($ages as $key => $age) {
if ($age > $age_var) {
$age_var = $age;
$oldest_key = $key;
}
}
echo "Oldest person is: {$names[$oldest_key]} ($age_var)";

Just for fun, here's another solution:
$names = array('jimmy', 'johnny', 'sarah');
$ages= array('16', '18', '12');
$people = array_combine($ages, $names);
ksort($people);
echo 'Oldest person is: '.end($people);
See it in action.
Note: If many people have the same age, the one appearing last in the input arrays gets picked. This is a result of the behavior of array_combine.

Related

How to select randomly from array exluding one value?

With the holidays slowly nearing, It's time to pick straws again. We always pick a piece of paper from a box containing everbody's name. However, this year I wanted to solve the issue of picking your own name from the box by using PHP.
I've got an array with names ex:
$names = [
'John',
'Jane',
'Joe',
'Matt',
'Steve',
'Anne',
'Karin'
];
For each of these names, I wanna pick 4 random names, so that at the end every person has 4 names for which they will have to buy a present.
The issue
Well, I'm stuck. I've thought of a million ways on how to do this but I just can't come up with anything.
What I've tried so far
Using a foreach
Using array_rand()
Shifting the array
The problem with these is that a person shouldn't be picking their own name and that everyone should be picked an even amount of times (4).
Update
Some great answers already posted. I'm not exactly sure though if this is fair for everyone. Everyone should at the end get 4 presents from 4 different persons.
I was thinking of adding each name to the $names array 4 times and then applying one of your answers. Am I on the right track with this?
Update 2
What I've tried now:
function select_rand($array, $exclude_array) {
$diff = array_diff($array, $exclude_array);
return $diff[array_rand($diff, 1)];
}
$workArray = [
'0' => $names,
'1' => $names,
'2' => $names,
'3' => $names,
];
foreach ($names as $k => $name) {
$i = 0;
$new[$name] = array();
while ($i < 4) {
$value = select_rand($workArray[$i], array_merge($new[$name], array($name)));
if (($key = array_search($value, $workArray[$i])) !== false) {
unset($workArray[$i][$key]);
}
$new[$name][] = $value;
$i++;
}
}
This works only in a few caes.
I would use shuffle, and array_slice for this job:
$names = [
'John',
'Jane',
'Joe',
'Matt',
'Steve',
'Anne',
'Karin'
];
foreach ($names as $name) {
// working array
$working = $names;
// remove current name from array,no one wants to buy presents for him/her self..
unset($working[$name]);
shuffle($working);
$people = array_slice($working, 0, 4);
echo $name . ' has to buy presents for:';
var_dump($people);
}
You can create custom function like as
$names = [
'John',
'Jane',
'Joe',
'Matt',
'Steve',
'Anne',
'Karin'
];
$my_name = "John";
$limit = 4;
function get_name($arr,$your_name,$limit){
$key = array_flip($arr)[$your_name];
unset($arr[$key]);
$rand_keys = array_rand($arr,$limit);
$result = array_intersect_key($arr, array_flip($rand_keys));
return implode(',',$result);
}
echo get_name($names,$my_name,$limit);
Demo
This can help -
function select_rand($array, $exclude_array) {
$diff= array_diff($array, $exclude_array);
return $diff[array_rand($diff, 1)];
}
$names = array(
'John',
'Jane',
'Joe',
'Matt',
'Steve',
'Anne',
'Karin'
);
foreach($names as $name)
{
$i = 0;
$new[$name] = array();
while($i < 4) {
$new[$name][] = select_rand($names, array_merge($new[$name], array($name)));
$i++;
}
}
This will generate a new array for each name (as key) in that array containing 4 unique names.
FIDDLE
Update
$new[$name][] = select_rand($names, array_merge($new[$name], array($name, 'Karin')));
I think if you want to have an even distribution of presents per person, you need to have more control over it. Anyhow, in this code I keep track of number of presents per person. I initialise it with zero: $presents = array_fill_keys($names, 0);. Then after each selection I updated this number $presents[$key]++;.
<?php
$names = array(
'John',
'Jane',
'Joe',
'Matt',
'Steve',
'Anne',
'Karin'
);
$presents_number = 4;
// initialization
$presents = array_fill_keys($names, 0);
$names_names = array();
foreach ($names as $i => $picker) {
$box = $names;
unset($box[$i]);
// filter out the people with maximum presents:
foreach ($presents as $key => $number) {
if (($presents[$key] > $presents_number-1) && in_array($key, $box)) {
$box = array_diff($box, array($key));
}
}
// shuffle the box and select 4 top
shuffle($box);
$selection = array_slice($box, 0, $presents_number);
foreach ($selection as $key) {
$presents[$key]++;
}
$names_names[$picker] = $selection;
}
echo "<pre>";
print_r($names_names);
echo "</pre>";
There can be more to be considered mathematically. Specially since loops can happen, this algorithm can go wrong. I haven't spend time on it. But as an example of 3 people and one present per person. (A, B, C)
correct answer:
A => {B}
B => {C}
C => {A}
wrong answer:
A => {B}
B => {A}
C => {}
Basically, the perfect algorithm should to avoid these wrong answers. Maybe later I fixed the problem as an update for this post.

PHP: Set value of nested array using variable as key

Lets say i have this kind of code:
$array = [
'a'=> [
'b' => [
'c'=>'some value',
],
],
];
$array['a']['b']['c'] = 'new value';
Of course this is working, but what i want is to update this 'c' key using variable, something like that:
$keys = '[a][b][c]';
$array{$keys} = 'new value';
But keys are treatening as string and this is what i get:
$array['[a][b][c]'] = 'new value';
So i would like some help, to show me the right way to make this work without using eval().
By the way, there can be any number of array nests, so something like this is not a good answer:
$key1 = 'a';
$key2 = 'b';
$key3 = 'c';
$array[$key1][$key2][$key3] = 'new value';
It isn't the best way to define your keys, but:
$array = [];
$keys = '[a][b][c]';
$value = 'HELLO WORLD';
$keys = explode('][', trim($keys, '[]'));
$reference = &$array;
foreach ($keys as $key) {
if (!array_key_exists($key, $reference)) {
$reference[$key] = [];
}
$reference = &$reference[$key];
}
$reference = $value;
unset($reference);
var_dump($array);
If you have to define a sequence of keys in a string like this, then it's simpler just to use a simple separator that can be exploded rather than needing to trim as well to build an array of individual keys, so something simpler like a.b.c would be easier to work with than [a][b][c]
Demo
Easiest way to do this would be using set method from this library:
Arr::set($array, 'a.b.c', 'new_value');
alternatively if you have keys as array you can use this form:
Arr::set($array, ['a', 'b', 'c'], 'new_value');
Hi bro you can do it like this throught an array of keys :
This is your array structured :
$array = array(
'a'=> array(
'b' => array(
'c'=>'some value',
),
),
);
This is the PHP code to get value from your array with dynamic keys :
$result = $array; //Init an result array by the content of $array
$keys = array('a','b','c'); //Make an array of keys
//For loop to get result by keys
for($i=0;$i<count($keys);$i++){
$result = $result[$keys[$i]];
}
echo $result; // $result = 'new value'
I hope that the answer help you, Find here the PHPFiddle of your working code.

Cleanest way of working out next variable name based on sequential order?

Hope my title explains it ok! Here's more detail:
I'm creating an array which stores keys & their values. Eg.
test1 = hello
test2 = world
test3 = foo
What is the cleanest way of working out what to call the next key? Let's say I will know the first part is 'test', but I don't know what the highest value number is. Obviously in this case I want it to be called 'test4'.
In the example below I want the next key to be 'test46', as it is the next highest value:
test6 = blah
test45 = boo
test23 = far
This sounds like you should be using an array with numerical indexes instead.
You could however use some code like this...
$arr = array('test6', 'test45', 'test23');
$max = 0;
foreach($arr as $value) {
$number = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
$max = max($max, $number);
}
$newKey = 'test' . ++$max; // string(6) "test46"
CodePad.
Implementation of #alex answer without using a loop:
$arr = array('test6', 'test45', 'test23');
$max = max(filter_var_array($arr, FILTER_SANITIZE_NUMBER_INT));
$newKey = 'test' . ++$max; // string(6) "test46"
CodePad
This data structure would be better stored as an array.
$test = array();
$test[] = 'hello';
$test[] = 'world';
$test[] = 'foo';
You then don't need to know the highest number to add a new item, just use the empty brackets syntax (shown above) to add an item to the end of the array.
You then have access to a wealth of array functions that PHP gives you to work with your data: http://php.net/manual/en/ref.array.php
When you want to get item 43 from the array, use:
echo $test[42];
Arrays are counted from 0 rather than 1, so item 43 will have an index of 42.
What are you using that for? If numbering the array is a must-have, just use a simple numerical indexed array instead, and simply prepend the key with "test" if you need it to show up as "test1":
<?php
$array = array(
6 => 'blah',
45 => 'boo',
23 => 'bar'
);
$array[] = 'new';
echo $array[46] . "\n"; // this is 'new'
foreach( $array as $key => $value ) {
echo "test$key = $value<br />\n"; // test6 = blah
}

Merge 2 arrays in CakePHP

I have two arrays array1 and array2. I want to merge these two arrays into one and show the values of merged array in a dropdown. I want the values in a way that the value of first array - value of 2nd array.
e.g:
$employeePlaces1 = array(1, 2, 4,9);
$employeePlaces2 = array(3, 5, 6,7);
I want in dropdown the value as $employeePlaces1[0]-$employeePlaces2[1],
$employeePlaces1[0]-$employeePlaces2[1].
1-3,
2-5,
4-6,
9-7.
How can I do this ?
$employee1 = array(1, 2, 4, 9);
$employee2 = array(3, 5, 6, 7);
function doMerge($n, $m) {
return $n.'-'.$m;
}
$c = array_map("doMerge", $employee1, $employee2);
print_r($c);
Or in PHP 5.3 syntax with lambda style functions:
$c = array_map(function($n, $m) {return $n.'-'.$m;}, $employee1, $employee2);
You can use the array_diff function
http://www.php.net/manual/en/function.array-diff.php
Answer for the edited question
//assuming both the arrays have the same length
echo "<select>";
for($i=0;$i<count($employeePlaces1);$i++)
{
echo "<option>".$employeePlaces1[i]." - ".$employeePlaces2[i]."</option>";
}
echo "</select>";
How about using array_combine?
http://www.php.net/manual/en/function.array-combine.php
Here is how you could manually loop through them and match the values together.
$list = array();
for($i=0; $i<=count($employeePlaces1); $i++) {
$list[] = $employeePlaces1[$i].'-'.$employeePlaces2[$i];
}
Haven't tested, but should be the gist of what you need.
Why not just loop over the arrays, i.e. do it longhand. Then you can get on with something else!
Edit in response to comment 1:
CakePHP is expecting:
<?php echo $this->Form->input('field', array('options' => array(
'Value 1'=>'Label 1',
'Value 2'=>'Label 2',
'Value 3'=>'Label 3'
))); ?>
so something like (pseudocode):
resultsArray = array();
loop
resultsArray[i] = inputArray_1[i]-inputArray_2[i];
endloop
in PHP (assumes size of array1 <= size of array2):
for($i=0;$i<count($inputArray_1);$i++)
{
$resultsArr[$i] = $inputArray_1[$i]-$inputArray_2[$i];
}

elegant way to map two arrays to each other

I've got two arrays, one with IDs and one with Names:
$ids = array(4, 13, 6, 8, 10);
$names = array('alice', 'bob', 'charles', 'david', 'elizabeth');
I need to update the db so that the rows with the ids have the names in the array. Here's the tricky bit: I also have two ints:
$special_name = 2; // the index in $names, in this case we mean 'charles'
$special_id = 13; // the id value
I don't care about which name goes to which id, except that the name with the $special_name should go on the $special_id.
What's the most elegant way to get there? All of the methods that I'm thinking of seem pretty messy. The best I've thought of is to extract out the special items from each array, and do those first, and then do the rest, perhaps building a new array like this:
$mapped = new array();
$mapped[$special_id] = $names[$special_name];
foreach ($ids as $id) {
if ($id != $special_id) {
$mapped[$id] = current($names);
}
// advance $names pointer
$next_name = next($names);
if ($next_name == $special_name) next($names);
}
I haven't tested that yet (I'm about to) but it's meant to produce something like:
$mapped = array(13=>'charles', 4=>'alice',6=>'bob', 8=>'david', 10=>'elizabeth');
and then running through that to do the actual update. Got a better idea?
UPDATE: added the possible solution above. Meanwhile a couple answers have come in.
If it wasn't for the special Ids, you could have just array_combine'd the two arrays. Here is how I think to have solved the issue:
Setup
$ids = array(4, 13, 6, 8, 10);
$names = array('alice', 'bob', 'charles', 'david', 'elizabeth');
$specialNameIndex = 2;
$specialId = 13;
Solution
$result = array($specialId => $names[$specialNameIndex]);
unset($ids[array_search($specialId, $ids)],
$names[$specialNameIndex]);
$result += array_combine($ids, $names);
Result
print_r($result);
Array
(
[13] => charles
[4] => alice
[6] => bob
[8] => david
[10] => elizabeth
)
you can use array_combine and then set/append your special values:
$mapped = array_combine($ids, $names);
$mapped[$special_id] = $names[$special_name];
Are the $ids and $names arrays synced? (Does 4 correspond to 'alice'?)
for ($i=0; $i < count($ids); $i++) {
$indexed[$ids[$i]] = $names[$i]; // $indexed[4] = 'alice';
$indexed2[] = array ( $ids[$i] => $names[$i] ); // $indexed[0] = ( 4 => 'alice')
}
Pick your fave
Since you use the default indexes you can use foreach() on keys($ids) to get the indexes so that you can iterate through both arrays at once. Just compare the value of the current index of $ids and use the alternate index of $names when appropriate.

Categories