我有一些用于对数据进行排序的逻辑,但根据用户输入,数据的分组方式不同。现在我有五个不同的功能,包含相同的逻辑但不同的分组。有没有办法组合这些功能,并动态设置一个正确分组的值。在功能中,这些任务正在发生
例如,有时我只是通过以下方式存储计算:
$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 []数组中的键,这样我就可以拥有一个函数而不是具有不同数组键的多个函数?
答案 0 :(得分:0)
执行以下操作会不会更容易
$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();
}
以前给出它,看看阵列结构是如何出现的。
答案 1 :(得分:0)
尝试使用开关盒。
<?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;
}
}
?>
答案 2 :(得分:0)
我同意@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>';
}
显然你可以更进一步,例如检查对象构造函数中是否存在数组键,如果没有提供,则给对象属性resource
一个默认值,依此类推,但这是一个开始OO方法。
答案 3 :(得分:0)
如果要动态设置和设置数组值,可以使用此方法。
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'))
将返回相当于$data['foo']['bar']['2017-08']
。
调用setVal($data,array('foo','bar','2017-08'),'hello')
将设置值,就像您调用了一样
$data['foo']['bar']['2017-08'] = 'hello'
。不存在的密钥将由 php magic 自动创建。
如果要动态构建数组结构,这可能很有用。
答案 4 :(得分:0)
这是我为在数组或对象上设置深层嵌套成员而编写的函数:
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.[]
答案 5 :(得分:0)
您可以使用this library通过键数组来获取或设置多维数组中的值:
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
设置为值。