Asked  1 Year ago    Answers:  5   Viewed   13 times

Looking into Kohana documentation, i found this really usefull function that they use to get values from a multidimensional array using a dot notation, for example:

$foo = array('bar' => array('color' => 'green', 'size' => 'M'));
$value = path($foo, 'bar.color', NULL , '.');
// $value now is 'green'

Im wondering if there is a way to set the an array value in the same way:

set_value($foo, 'bar.color', 'black');

The only way i found to do that is re-building the array notation ($array['bar']['color']) and then set the value.. using eval.

Any idea to avoid eval?

 Answers

3
function set_val(array &$arr, $path,$val)
{
   $loc = &$arr;
   foreach(explode('.', $path) as $step)
   {
     $loc = &$loc[$step];
   }
   return $loc = $val;
}
Thursday, April 1, 2021
 
laurent
 
4

You need to iterate over your results, adding a new entry to the output when you encounter a new team, or updating the points value when you find the same team again. This is most easily done by initially indexing the output by the team name, and then using array_values to re-index the array numerically:

$teams = array();
foreach ($results as $result) {
    $team = $result['team'];
    if (!isset($teams[$team])) {
        $teams[$team] = array('team' => $team, 'points' => $result['punti']);
    }
    else {
        $teams[$team]['points'] += $result['punti'];
    }
}
$teams = array_values($teams);
print_r($teams);

Output (for your sample data):

Array
(
    [0] => Array
        (
            [team] => Red Bull Racing
            [points] => 418
        )
    [1] => Array
        (
            [team] => Scuderia Ferrari
            [points] => 353
        )
    [2] => Array
        (
            [team] => Mercedes-AMG
            [points] => 516
        )
    [3] => Array
        (
            [team] => Racing Point F1
            [points] => 147
        )
    [4] => Array
        (
            [team] => Haas F1
            [points] => 127
        )
)

Demo on 3v4l.org

Thursday, April 1, 2021
 
Fredy
 
3

The behavior that you are experiencing is because the undefined property of the Global object, is mutable on any ECMAScript 3 based implementation. (latest Chrome versions are implementing ES5, but this behavior is still present).

Let's examine the second snippet:

var x = window.foo;
window[x] = null;
alert( window.bar === undefined );

The x variable will hold the undefined value, since the foo property does not exist.

By assigning window[x] = null, you are overriding the value of the undefined property:

window[x] = null; // is equivalent to
window['undefined'] = null; // or
window.undefined = null; //

(In your first snippet, when you assign window.x = null, you are creating a property named "x" on the window object.)

Therefore (in your second snippet), the undefined property will hold null, and window.bar will produce undefined:

alert( window.bar === undefined ); // false
alert( undefined  === null ); // false

The undefined property was not specified as { ReadOnly } on ECMAScript 3, (along with his friends NaN, Infinity).

This has changed in ECMAScript 5, those properties are described as non-writables.

Wednesday, August 18, 2021
3

You can do it like this, do the calculation from the innermost of the array. Check the demo.

<?php
function f(&$array)
{
    foreach($array as $k => &$v)
    {
        if(is_array($v))
        {
            if(count($v) == count($v, 1))
            {
                unset($array[$k]);
                if($k == 'sum')
                {
                    $v =  array_sum($v);
                    $array[] = $v;

                }elseif($k == 'multiply'){
                    $v = array_product($v);
                    $array[] = $v;
                }else{

                    foreach($v as $vv)
                        $array[] = $vv;
                }
            }else
                f($v);
        }
    }
}

while(count($array) != count($array, 1))
{
    f($array);
}

print_r($array);

Note:

traverse array from outer to inner
traverse array from inner to outer

Sunday, December 5, 2021
 
4

The dot syntax is usually applied to declared properties but that’s not mandatory. Using obj.valueA and obj.valueB does work.

The error message you’re getting is probably due to the object not having explicit type MyClass *. For example, the following works:

MyClass *obj1 = [MyClass new];
NSLog(@"%f %f %f", obj1.valueA, obj1.valueB, [obj1 add]);

On the other hand:

MyClass *obj1 = [MyClass new];
NSLog(@"%f %f %f", obj1.valueA, obj1.valueB, [obj1 add]);

id obj2 = obj1;
NSLog(@"%f %f %f", obj2.valueA, obj2.valueB, [obj2 add]);

gives:

error: request for member ‘valueA’ in something not a structure or union
error: request for member ‘valueB’ in something not a structure or union

because obj2 has type id, so the compiler doesn’t have enough information to know that .valueA and .valueB are actually the getter methods -valueA and -valueB. This can happen if you place objects of type MyClass in an NSArray and later retrieve them via -objectAtIndex:, since this method returns a generic object of type id.

To appease the compiler, you need to cast the object to MyClass * and only then use the dot syntax. You could accomplish this by:

MyClass *obj2 = obj1;
// or
MyClass *obj2 = [someArray objectAtIndex:someIndex];
// and then
obj2.valueA

or, if obj2 is declared as id:

((MyClass *)obj2).valueA

or, if the object is returned by a method whose return type is id:

((MyClass *)[someArray objectAtIndex:someIndex]).valueA

Alternatively, you could simply get rid of the dot syntax altogether (my favourite):

[obj2 valueA]
[[someArray objectAtIndex:someIndex] valueA]
Monday, January 10, 2022
 
r2evans
 
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 :