Asked  7 Months ago    Answers:  5   Viewed   40 times

I'm trying to select the maximum value for a particular key in a multidimensional array. I'm having trouble "getting to" the key in question...

So, the array (which is much more lengthy than what I'm posting here)

[0] => stdClass Object
    (
        [id] => 70
        [cust] => 4
        [dnum] => 1
        [upper] => Array
            (
                [0] => 66
            )

    )
[1] => stdClass Object
    (
        [id] => 43
        [cust] => 42
        [dnum] => 2
        [upper] => Array
            (
                [0] => 77
            )

    )
[2] => stdClass Object
    (
        [id] => 12
        [cust] => 3
        [dnum] => 0
        [upper] => Array
            (
                [0] => 99
            )

    )

I'm trying to find the maximum "dnum" value across the entire array, so in this example, $max = 2. I know that the max function allows me to do this, but I'm not sure how to reference the dnum element without putting the whole thing in a foreach loop, and if I do that, then max wouldn't be the function to use, right?

So, I can't exactly do this:

$max = max($myarray[]->dnum);

Is there a way for me to do this without having to recreate the entire array?

 Answers

25
$max = 0;
foreach($array as $obj)
{
    if($obj->dnum > $max)
    {
        $max = $obj->dnum;
    }
}

That function would work correctly if your highest number is not negative (negatives, empty arrays, and 0s will return the max as 0).

Because you are using an object, which can have custom properties/structures, I don't believe there are really any 'predefined' functions you can use to get it. Might as well just use a foreach loop.

You really can't get away from a foreach loop, as even internal functions use a foreach loop, it is just behind the scenes.

Another solution is

$numbers = array();
foreach($array as $obj)
{
    $numbers[] = $obj->dnum;
}
$max = max($numbers);
Wednesday, March 31, 2021
 
Ula
answered 7 Months ago
Ula
94

The problem could be resolved by changing public function offsetGet($name) to public function &offsetGet($name) (by adding return by reference), but it will cause Fatal Error ("Declaration of ArrayTest::offsetGet() must be compatible with that of ArrayAccess::offsetGet()").

PHP authors screwed up with this class some time ago and now they won't change it in sake of backwards compatibility:

We found out that this is not solvable without blowing up the interface and creating a BC or providing an additional interface to support references and thereby creating an internal nightmare - actually i don't see a way we can make that work ever. Thus we decided to enforce the original design and disallow references completley.

Edit: If you still need that functionality, I'd suggest using magic method instead (__get(), __set(), etc.), because __get() returns value by reference. This will change syntax to something like this:

$arrTest->test['bar'] = 5;

Not an ideal solution of course, but I can't think of a better one.

Update: This problem was fixed in PHP 5.3.4 and ArrayAccess now works as expected:

Starting with PHP 5.3.4, the prototype checks were relaxed and it's possible for implementations of this method to return by reference. This makes indirect modifications to the overloaded array dimensions of ArrayAccess objects possible.

Wednesday, March 31, 2021
 
michele
answered 7 Months ago
10

The code you already wrote almost works. The problem is that it will just immediately print the key each time it encounters one that matches the id during the foreach loop.

foreach($arr as $key => $array) {
    if ( $array['from']['id'] === $id) {
        echo $key."nn";
    }
}

If instead you store the key in a variable, then after the loop is finished, the value in the variable will be the last one, and you can just print that.

$last = "";
foreach($arr as $key => $array) {
    if ( $array['from']['id'] === $id) {
        $last = $key;
    }
}
echo $last."nn";
Wednesday, March 31, 2021
 
ChronoFish
answered 7 Months ago
51

Well, if you're keys are unique relatively to all levels, you could do:

array_walk_recursive($options, function($value, $key){
  if($value && in_array($key, array('menu_slug', 'page_title', 'option_group', 'core_template')))
    print $value;  
});

:)

But I assume that your real purpose is to wrap this text in HTML strings, so you should use switch instead of my if statement and print whatever you want. If you need to print the stuff in a certain order, use a temporary array to store the output you generate, and print it after you're done.

Saturday, May 29, 2021
 
JakeGR
answered 5 Months ago
69

Best practice in Karate is to NOT use JS for loops at all. It results in cleaner, more readable code:

* def fun = function(x){ return { max: x.day.maxtemp_c, date: x.date } }
* def list = karate.map(response.forecast.forecastday, fun)
* def max = 0
* def index = 0
* def finder =
"""
function(x, i) {
  var max = karate.get('max');
  if (x.max > max) {
    karate.set('max', x.max);
    karate.set('index', i);
  }  
}
"""
* karate.forEach(list, finder)
* print 'found at index', index
* print 'item:', list[index]

Note how easy it is to re-shape a given JSON, the result of list here would be:

[
  {
    "max": 9,
    "date": "2020-03-03"
  },
  {
    "max": 8,
    "date": "2020-03-04"
  },
  {
    "max": 7,
    "date": "2020-03-05"
  }
]
Friday, August 27, 2021
 
shin
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :