如何在php中动态设置数组键

发布于 2024-09-19 06:22:48 字数 1055 浏览 5 评论 0原文

我有一些逻辑用于对数据进行排序,但根据用户输入,数据的分组方式不同。现在我有五个不同的函数,它们包含相同的逻辑但不同的分组。有没有办法组合这些函数并动态设置一个可以正确分组的值。在函数内,这些分配正在发生

例如,有时我简单地存储计算:

$calcs[$meter['UnitType']['name']] = ...

但其他时候需要更具体的分组:

$calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] =...

正如您所看到的,有时它存储在多维数组中,有时则不存储在多维数组中。我一直在尝试使用 eval() 但没有成功(不确定这是正确的方法)。将数据存储在临时变量中并不会真正节省太多,因为有许多嵌套循环和 if 语句,因此必须在多个位置重复数组。

编辑

我希望下面的示例更好地解释我的问题。这显然是一个简化版本:

if(){
     $calcs[$meter['UnitType']['name']] = $data;
} else {
    while () {
       $calcs[$meter['UnitType']['name']] = $data;
    }
} 

现在可以使用相同的逻辑,但将其存储在不同的键中:

if(){
     $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
} else {
    while () {
       $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
    }
} 

有没有一种方法可以抽象出 $calc[] 数组中的键,以便我可以拥有一个函数而不是多个函数具有不同数组键的函数?

I have some logic that is being used to sort data but depending on the user input the data is grouped differently. Right now I have five different functions that contain the same logic but different groupings. Is there a way to combine these functions and dynamically set a value that will group properly. Within the function these assignments are happening

For example, sometimes I store the calculations simply by:

$calcs[$meter['UnitType']['name']] = ...

but other times need a more specific grouping:

$calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] =...

As you can see sometimes it is stored in a multidiminesional array and other times not. I have been trying to use eval() but without success (not sure that is the correct approach). Storing the data in a temporary variable does not really save much because there are many nested loops and if statements so the array would have to be repeated in multiple places.

EDIT

I hope the following example explains my problem better. It is obviously a dumbed down version:

if(){
     $calcs[$meter['UnitType']['name']] = $data;
} else {
    while () {
       $calcs[$meter['UnitType']['name']] = $data;
    }
} 

Now the same logic can be used but for storing it in different keys:

if(){
     $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
} else {
    while () {
       $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
    }
} 

Is there a way to abstract out the keys in the $calc[] array so that I can have one function instead of having multiple functions with different array keys?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

北城半夏 2024-09-26 06:22:48

如果您想动态获取和设置数组值,可以使用它。

function getVal($data,$chain){
    $level = $data;
    for($i=0;$i<count($chain);$i++){
        if(isset($level[$chain[$i]]))
            $level = $level[$chain[$i]];
        else
            return null; // key does not exist, return null
    }
    return $level;
}

function setVal(&$data,$chain,$value){
    $level = &$data;
    for($i=0;$i<count($chain);$i++){
        $level = &$level[$chain[$i]]; // set reference (&) in order to change the value of the object
    }
    $level = $value;
}

工作原理

调用 getVal($data,array('foo','bar','2017-08')) 将返回与 $ 等效的值数据['foo']['bar']['2017-08'].

调用 setVal($data,array('foo','bar','2017-08'),'hello') 将设置值,就像您调用一样
$data['foo']['bar']['2017-08'] = '你好'。不存在的密钥将由 php magic 自动创建。

如果您想动态构建数组的结构,这会很有用。

You can use this if you want to get&set array values dynamically.

function getVal($data,$chain){
    $level = $data;
    for($i=0;$i<count($chain);$i++){
        if(isset($level[$chain[$i]]))
            $level = $level[$chain[$i]];
        else
            return null; // key does not exist, return null
    }
    return $level;
}

function setVal(&$data,$chain,$value){
    $level = &$data;
    for($i=0;$i<count($chain);$i++){
        $level = &$level[$chain[$i]]; // set reference (&) in order to change the value of the object
    }
    $level = $value;
}

How it works:

Calling getVal($data,array('foo','bar','2017-08')) will return the equivalent of $data['foo']['bar']['2017-08'].

Calling setVal($data,array('foo','bar','2017-08'),'hello') will set value as if you called
$data['foo']['bar']['2017-08'] = 'hello'. non-existent keys will be created automatically by php magic.

This can be useful if you want to build the structure of the array dynamically.

永不分离 2024-09-26 06:22:48

执行以下操作不是更容易吗?

$calcs = array(
    $meter['Resource']['name'] => array(
        $meter['UnitType']['name'] => 'Some Value',
        $meter['UnitType']['name2'] => 'Some Value Again'
    ),
);

或者您可以使用对象,

$calcs = new stdClass();
$calcs->{$meter['UnitType']['name']} = 'Some Value';

但我建议您在数组中构建结构,然后执行!

$calcs = (object)$calcs_array;

或者您可以将第一个数组循环到一个新数组中!

$new = array();
$d = date('Y-m',$start);
foreach($meter as $key => $value)
{
    $new[$key]['name'][$d] = array();
}

给过去看看数组结构如何出来。

Would it not be easier to do the following

$calcs = array(
    $meter['Resource']['name'] => array(
        $meter['UnitType']['name'] => 'Some Value',
        $meter['UnitType']['name2'] => 'Some Value Again'
    ),
);

or you can use Objects

$calcs = new stdClass();
$calcs->{$meter['UnitType']['name']} = 'Some Value';

but I would advice you build your structure in arrays and then do!

$calcs = (object)$calcs_array;

or you can loop your first array into a new array!

$new = array();
$d = date('Y-m',$start);
foreach($meter as $key => $value)
{
    $new[$key]['name'][$d] = array();
}

Give it ago and see how the array structure comes out.

書生途 2024-09-26 06:22:48

这是我编写的用于在数组或对象上设置深层嵌套成员的函数:

function dict_set($var, $path, $val) {
    if(empty($var))
        $var = is_array($var) ? array() : new stdClass();

    $parts = explode('.', $path);
    $ptr =& $var;

    if(is_array($parts))
    foreach($parts as $part) {
        if('[]' == $part) {
            if(is_array($ptr))
                $ptr =& $ptr[];

        } elseif(is_array($ptr)) {
            if(!isset($ptr[$part]))
                $ptr[$part] = array();

            $ptr =& $ptr[$part];

        } elseif(is_object($ptr)) {
            if(!isset($ptr->$part))
                $ptr->$part = array();

            $ptr =& $ptr->$part;
        }
    }

    $ptr = $val;

    return $var;
}

使用示例数据:

$array = [];

$array = dict_set($array, 'resource1.unit1.2017-10', 'value1');
$array = dict_set($array, 'resource1.unit2.2017-11', 'value2');
$array = dict_set($array, 'resource2.unit1.2017-10', 'value3');

print_r($array);

结果输出如下:

Array
(
    [resource1] => Array
        (
            [unit1] => Array
                (
                    [2017-10] => value1
                )

            [unit2] => Array
                (
                    [2017-11] => value2
                )

        )

    [resource2] => Array
        (
            [unit1] => Array
                (
                    [2017-10] => value3
                )

        )

)

dict_set() 的第二个参数是 $path 点符号中的字符串。您可以使用动态键来构建它,并在各部分之间使用句点分隔符。该函数适用于数组和对象。

它还可以通过使用 [] 作为 $path 的元素将增量成员附加到深层嵌套数组。例如:parent.child.child.[]

Here's a function I wrote for setting deeply nested members on arrays or objects:

function dict_set($var, $path, $val) {
    if(empty($var))
        $var = is_array($var) ? array() : new stdClass();

    $parts = explode('.', $path);
    $ptr =& $var;

    if(is_array($parts))
    foreach($parts as $part) {
        if('[]' == $part) {
            if(is_array($ptr))
                $ptr =& $ptr[];

        } elseif(is_array($ptr)) {
            if(!isset($ptr[$part]))
                $ptr[$part] = array();

            $ptr =& $ptr[$part];

        } elseif(is_object($ptr)) {
            if(!isset($ptr->$part))
                $ptr->$part = array();

            $ptr =& $ptr->$part;
        }
    }

    $ptr = $val;

    return $var;
}

Using your example data:

$array = [];

$array = dict_set($array, 'resource1.unit1.2017-10', 'value1');
$array = dict_set($array, 'resource1.unit2.2017-11', 'value2');
$array = dict_set($array, 'resource2.unit1.2017-10', 'value3');

print_r($array);

Results in output like:

Array
(
    [resource1] => Array
        (
            [unit1] => Array
                (
                    [2017-10] => value1
                )

            [unit2] => Array
                (
                    [2017-11] => value2
                )

        )

    [resource2] => Array
        (
            [unit1] => Array
                (
                    [2017-10] => value3
                )

        )

)

The second argument to dict_set() is a $path string in dot-notation. You can build this using dynamic keys with period delimiters between the parts. The function works with arrays and objects.

It can also append incremental members to deeply nested array by using [] as an element of the $path. For instance: parent.child.child.[]

无边思念无边月 2024-09-26 06:22:48

尝试使用开关盒。

<?php
$userinput = $calcs[$meter['UnitType']['name']] = $data;;

switch ($userinput) {
  case "useriput1":
    while () {
        $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
    }
    break;
  case "userinput2":
    while () {
        $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
    }
    break;

  ...

  default:
    while () {
        $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
    }
}
?>

Try to use a switch case.

<?php
$userinput = $calcs[$meter['UnitType']['name']] = $data;;

switch ($userinput) {
  case "useriput1":
    while () {
        $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
    }
    break;
  case "userinput2":
    while () {
        $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
    }
    break;

  ...

  default:
    while () {
        $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
    }
}
?>
两相知 2024-09-26 06:22:48

我同意 @Jake N 对 OP 的评论,也许使用对象是更好的方法。尽管如此,如果您想使用数组,您可以检查条件中是否存在键,如下所示:

if(
    array_key_exists('Resource', $meter)
) {
    $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
} else {
    $calcs[$meter['UnitType']['name']] = $data;
}

另一方面,如果您想使用对象,您可以创建一个 MeterReading 对象类型,然后将 MeterReading 实例作为数组元素添加到 $calcs 数组中,如下所示:

// Object defintion
class MeterReading {
    private $data;
    private $resource;
    private $startDate;
    private $unitType;

    public function __construct(Array $meter, $start, $data) {
        $this->unitType   = $meter['UnitType']['name'];
        $this->resource   = $meter['Resource']['name'];
        $this->startDate  = date('Y-m',$start);
    }

    public function data() {
        return $this->data;
    }

    public function resource() {
        return $this->resource;
    }

    public function startDate() {
        return $this->startDate;
    }

    public function unitType() {
        return $this->unitType;
    }
}

// Example population
$calcs[] = new MeterReading($meter, $start, $data);

// Example usage
foreach($calcs as $calc) {
    if($calc->resource()) {
        echo 'Resource: ' . $calc->resource() . '<br>';
    }
    echo 'Unit Type: ' . $calc->unitType() . '<br>';
    echo 'Start Date: ' . $calc->startDate() . '<br>';
    echo 'Data: ' . $calc->data() . '<br>';
}

显然,您可以更进一步,例如检查对象中是否存在数组键构造函数,如果没有提供,则为对象属性资源提供默认值,等等,但这是面向对象方法的开始。

I agree with the comment on the OP by @Jake N that perhaps using objects is a better approach. Nonetheless, if you want to use arrays, you can check for the existence of keys in a conditional, like so:

if(
    array_key_exists('Resource', $meter)
) {
    $calcs[$meter['Resource']['name']][$meter['UnitType']['name']][date('Y-m',$start)] = $data;
} else {
    $calcs[$meter['UnitType']['name']] = $data;
}

On the other hand, if you want to use objects, you can create a MeterReading object type, and then add MeterReading instances as array elements to your $calcs array, like so:

// Object defintion
class MeterReading {
    private $data;
    private $resource;
    private $startDate;
    private $unitType;

    public function __construct(Array $meter, $start, $data) {
        $this->unitType   = $meter['UnitType']['name'];
        $this->resource   = $meter['Resource']['name'];
        $this->startDate  = date('Y-m',$start);
    }

    public function data() {
        return $this->data;
    }

    public function resource() {
        return $this->resource;
    }

    public function startDate() {
        return $this->startDate;
    }

    public function unitType() {
        return $this->unitType;
    }
}

// Example population
$calcs[] = new MeterReading($meter, $start, $data);

// Example usage
foreach($calcs as $calc) {
    if($calc->resource()) {
        echo 'Resource: ' . $calc->resource() . '<br>';
    }
    echo 'Unit Type: ' . $calc->unitType() . '<br>';
    echo 'Start Date: ' . $calc->startDate() . '<br>';
    echo 'Data: ' . $calc->data() . '<br>';
}

Obviously you can take this further, such as checking the existence of array keys in the object constructor, giving the object property resource a default value if not provided, and so on, but this is a start to an OO approach.

沦落红尘 2024-09-26 06:22:48

您可以使用 此库 使用键数组获取或设置多维数组中的值:

Arr::getNestedElement($calcs, [
    $meter['Resource']['name'], 
    $meter['UnitType']['name'], 
    date('Y-m', $start)
]);

获取值或:

Arr::handleNestedElement($calcs, [
    $meter['Resource']['name'], 
    $meter['UnitType']['name'], 
    date('Y-m', $start)
], $data);

$data 设置为值。

You can use this library to get or set value in multidimensional array using array of keys:

Arr::getNestedElement($calcs, [
    $meter['Resource']['name'], 
    $meter['UnitType']['name'], 
    date('Y-m', $start)
]);

to get value or:

Arr::handleNestedElement($calcs, [
    $meter['Resource']['name'], 
    $meter['UnitType']['name'], 
    date('Y-m', $start)
], $data);

to set $data as value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文