Why is this array_search returning 0 - php

Consider the following:
$characterStats = [
['strength' => 500],
['dexterity' => 200],
['agility' => 1000],
['intelligence' => 1200],
['health' => 675],
];
$stat = array_search(max($characterStats), $characterStats);
echo $stat;
What I expect: ['intelligence' => 1200]
What I get: 0
Can some one help me out to achieve what I want?

Try the following:
$characterStats = array(
'strength' => 500,
'dexterity' => 200,
'agility' => 1000,
'intelligence' => 1200,
'health' => 675,
);
$stat = array_search(max($characterStats), $characterStats);
echo $stat;
I changed the way the array is declared. I believe you may need to indicate the field name you would like to search if using nested arrays with the following call:
$stat = array_search(max($characterStats), array_column($characterStats, 'KEYNAME'));
However, since each sub array has only 1 element with different "key" it may not be the best approach. For your scenario, you may need to use another approach, where you loop through each element and store the max value found.

With the array as you have it at the moment, the easiest way I can think of doing it as a standard foreach() and keep the maximum value as well as the element where it's found (save doing another search to get the full entry)...
$characterStats = [
['strength' => 500],
['dexterity' => 200],
['agility' => 1000],
['intelligence' => 1200],
['health' => 675],
];
$maxStat = null;
$max = null;
foreach ( $characterStats as $stat ){
if ( current($stat) > $max ) {
$max = current($stat);
$maxStat = $stat;
}
}
print_r( $maxStat);

Related

tried to bind parameter number 2101. sql server supports a maximum of 2100 parameters

I am trying to run some migrations through phinx to MSSQL, when I execute my query turns out getting the following message "tried to bind parameter number 2101. sql server supports a maximum of 2100 parameters"
I have been looking for a solution for like 3 days, does anyone know, what can be the problem and how can I fix it? could be a problem related to my php migration file? or something about my phinx configuration?
This is part of my migration file:
$rows =
[
[
'COLUMNA' => 111,
'COLUMNB' => 101,
'COLUMNC' => '-1',
'COLUMND' => '',
'COLUMNE' => 'ERROR',
'COLUMNF' => NULL,
'COLUMNG' => 1,
'COLUMNH' =>0,
'COLUMNI' => 10002,
'COLUMNJ' => '2017-11-12 00:00:00.000',
'COLUMNK' => -1,
'COLUMNM' => -1
],
[ 'COLUMNA' => 112,
'COLUMNB' => 101,
'COLUMNC' => '-1',
'COLUMND' => '',
'COLUMNE' => 'ERROR',
'COLUMNF' => NULL,
'COLUMNG' => 1,
'COLUMNH' =>0,
'COLUMNI' => 10002,
'COLUMNJ' => '2017-11-12 00:00:00.000',
'COLUMNK' => -1,
'COLUMNM' => -1
],
]
$X = $this->table('MYTABLE');
$X->insert($rows);
$X->saveData();
Thanks a lot
You can chunk your data with php easily. If you want you can also determine a good chunksize by checking your data size.
$chunk_size = floor(2100 / count($rows[0]));
foreach (array_chunk($rows, $chunk_size) as $data_chunk ) {
$X->insert($data_chunk)->saveData();
}
Obviously you are trying to bind too many parameters, solution is to do the migrations in batches of lets say 1000 rows ~ 12000 parames according to your data.
$X = $this->table('MYTABLE');
$data = [];
for ($i = 0; $i < count($rows); i++)
{
$data[] = $rows[i];
if(i % 1000 === 0)
{
$X->insert($data);
$X->saveData();
$data = [];
}
}

Dynamically apply a key/value pair to an array in one go (within first definition)

Imagine this situation:
$component = array(
'type' => 'chimney',
'material' => 'stone'
);
What i would like to do is to add a key/value pair to this array, if a certain condition is met.
$hasMetrics = true;
$component = array(
'type' => 'chimney',
'material' => 'stone',
'metrics' => ($hasMetrics ? array('width' => 60, 'height' => 2000) : false)
);
While this could be used, it will always cause a key called 'metrics' in my array.
Of course, if i don't want that, i could use array_merge() to merge a second array with the first (the second being either an empty array or the desired key/value pair, depending on the condition).
But what i am longing to find out is if there is any way to define this array like above, while taking care of $hasMetrics, without the use of any other means (such as array_merge()) but purely in the actual (first and only) definition of this array.
Like this: (non-applicable, demonstrative example)
$component = array(
'type' => 'chimney',
'material' => 'stone',
($hasMetrics ? array('metrics' => array(
'width' => 60,
'height' => 2000
)) : false)
);
(This, as i understand it, would generate two keys (type and material and then create one keyless value that is, itself, an array containing a key (metrics) and another array as value.)
Can anyone show me some proper approach? Perhaps there is some kind of PHP function available, with special properties (such as list() which is capable of cross-assignment).
EDIT
Perhaps some more clarification is needed, as many answers point out ways to go such as:
Using a followup assignment to a certain key
Filtering the generated array after defining it
While these are perfectly valid ways to extend the array, but i am explicitly looking for a way to do this in one go within the one array definition.
Not with the array defenition itself. I would add it to the array if necessary:
if($hasMetrics) {
$component['metrics'] = array('width' => 60, 'height' => 2000);
}
$hasMetrics = true;
$component = array(
'type' => 'chimney',
'material' => 'stone',
);
if($hasMetrics){
$component['metrics'] = array('width' => 60, 'height' => 2000);
}
Try
$component = array(
'type' => 'chimney',
'material' => 'stone',
'metrics' => $hasMetrics ? array('width' => 60, 'height' => 2000) : ''
);
And after that
$component = array_filter( $component ); // remove if it has '' value
OR
$component = array(
'type' => 'chimney',
'material' => 'stone',
);
if($hasMetrics) {
$component['metrics'] = array('width' => 60, 'height' => 2000);
}

mongodb: finding the highest numeric value of a column

I have MongoDB collection of documents containing several fields. One of the columns/fields should be numeric only, but some of these fields contain non-numerical (corrupt) data as string values. I should find the highest numerical value of this column, excluding the corrupt, non-numerical data. I am aware of the question Getting the highest value of a column in MongoDB, but AFAIK, this extended case was not covered.
The example below depicts the issue. For the highest value, the document with "age": 70 should be returned:
[
{
"id": "aa001",
"age": "90"
},
{
"id": "bb002",
"age": 70
},
{
"id": "cc003",
"age": 20,
}
]
Providing a PHP example for the find() / findOne() query would be of much help. Thanks a lot!
JohnnyHK came up with the perfect solution. Here's the working PHP code:
$cursor = $collection->find(array('age' => array('$not' => array('$type' => 2))), array('age' => 1));
$cursor->sort(array('age' => -1))->limit(1);
You can use the $type operator with $not in your query to exclude docs where age is a string. In the shell your query would look like:
db.test.find({age: {$not: {$type: 2}}}).sort({age: -1}).limit(1)
Or in PHP from Martti:
$cursor = $collection->find(array('age' => array('$not' => array('$type' => 2))), array('age' => 1));
$cursor->sort(array('price' => -1))->limit(1);
with PHP driver (mongodb)
using findOne()
$filter=[];
$options = ['sort' => ['age' => -1]]; // -1 is for DESC
$result = $collection->findOne(filter, $options);
$maxAge = $result['age']
You can use aggregate function to get maximum number from collections like this.
$data=$collection->aggregate(array
( '$group'=>
array('_id'=>'',
'age'=>array('$max'=>'$age'.)
)
)
);
This works for me
$options = ['limit' => 100,'skip' => 0, 'projection' => ['score' => ['$meta' => 'textScore']], 'sort' => ['score' => ['$meta' => 'textScore']]];

PHP multidimensional array counter

Im trying to make a multidimensional array with two columns. Name and Counter. I can do a single array with all the names. But I dont know how to make it multidimensional and be able to still update the counters. Code i got so far is
if (!in_array($prodname, $da)){
array_push($da, $prodname);
}
and then I can dump it back out with a foreach. How do I make it two dimensional? How can I say alright this exists update the old value? etc.
If you only need name and counter then you should just be able to use a normal array:
$nameCountArray = array();
foreach($names as $name){
if(!array_key_exists($name,$nameCountArray)){
$nameCountArray[$name] = 1;
}else{
$nameCountArray[$name] = $nameCountArray[$name] + 1;
}
}
If you do need multidimensional arrays these are just arrays of arrays and can be accessed as such. A good example of this is using a 2d array to store locations (say on a 3 by 3 grid):
$twoDArray = array(
0 => array(0 => 1,
1 => 4,
2 => 7),
1 => array(0 => 2,
1 => 5,
2 => 8),
2 => array(0 => 3,
1 => 6,
2 => 9)
);
//Grab the item at 1,2
$item = $twoDArray[1][2];//Will give '8'
Supposing you want $da to look like this:
Array(
"name1" => array("score1" => 80, "score2" => 100),
"name2" => array("score1" => 50, "score2" => 60),
"name3" => array("score1" => 90, "score2" => 80),
...
)
Then all you need to do is something like:
function setScore($prodName, $scoreName, $score)
{
global $da;
if (!array_key_exists($prodName, $da)) {
$da[$prodName] = array();
}
$da[$prodName][$scoreName] = $score;
}
setScore("name1", "score1", 80);
setScore("name1", "score2", 100);
setScore("name2", "score1", 50);
...
Unless I'm misunderstanding your question, which is very possible.

Using supplier with largest margin using PHP logic

I have the following values from a database call that I want to apply some logic to. I thought I could originally use PHP's max however this doesn't appear to be the case.
I have three suppliers of a product. They might not all stock the item I am displaying, and they all offer a different margin, on a product by product basis though, so that is why I can't just say generally supplier 1 is better than supplier 2 etc.
$supplier1Live = 1
$supplier2Live = 1
$supplier3Live = 0
$marginSupplier1 = 20
$marginSupplier2 = 40
$martinSupplier3 = 50
In this example I would want to use Supplier 2 as they stock the product supplier2Live = 1 and also have the better margin than the other supplier who stocks the product (supplier1)
My mind however is drawing a complete blank in how to code this?
I thought I could add it to an array giving:
$array = array(
"supplier1" => array(
"live" => 1,
"margin" => 20
),
"supplier2" => array(
"live" => 1,
"margin" => 40
),
"supplier3" => array(
"live" => 0,
"margin" => 50
)
);
And run something on that, but not sure what to.
Filter the array using array_filter (filter by live==1), and then find the maximum out of the resultant array (maximum on the "margin" value)
Like this, if I understand correctly
$array = array(
"supplier1" => array(
"live" => 1,
"margin" => 20
),
"supplier2" => array(
"live" => 1,
"margin" => 40
),
"supplier3" => array(
"live" => 0,
"margin" => 50
)
);
$res = array_filter($array,function($v){return $v["live"];});
$supplier = array_reduce($res, function($a, $b){
return $a["margin"]>$b["margin"]?$a:$b;
});
print_r($supplier);
Try something like this:
$best_supplier = null;
$best_supplier_margin = null;
foreach($array as $name => $supplier) {
if($supplier['live']) {
if($supplier['margin'] > $best_supplier_margin || is_null($best_supplier_margin)) {
$best_supplier = $name;
$best_supplier_margin = $supplier['margin'];
}
}
}
if(is_null($best_supplier)) throw new Exception('No suppliers are live!');
echo $best_supplier;
So you basically want to find the max of supplierXLive * marginSupplierX?
You can also implement a custom compare function and provide it to PHPs usort() function

Categories