创建对象

时间:2016-10-03 19:57:59

标签: php foreach

我有什么

所以我有一个名为result的变量,其格式如下:

Array
(
[0] => stdClass Object
    (
        [description] => dev1
        [id] => 09A
        [sum] => 52
        [completed_pct_completed] => 97.97
        [completed_pct_1msec] => 11.44
        ....
    )

[1] => stdClass Object
    (
        [description] => dev1
        [id] => 273
        [sum] => 59
        [completed_pct_completed] => 94.43
        [completed_pct_1msec] => 10.95
        ....
    )

[2] => stdClass Object
    (
        [description] => dev1.1
        [id] => 28A
        [sum] => 39
        [completed_pct_completed] => 95.55
        [completed_pct_1msec] => 20.78
        ....
    )
[3] => stdClass Object
    (
        [description] => dev1.1
        [id] => 28B
        [sum] => 31
        [completed_pct_completed] => 91.55
        [completed_pct_1msec] => 28.78
        ....
    )
....

大约有250种不同的物体。这个当前顺序的问题在于每个的描述变得多余,以至于我只想将每个描述的所有数据放入对象中。描述按dev1.x进行,其中x可以是不同的数字或字母或其他什么,并不重要。

我想做什么:

我试图将$result重新排序为以下格式。实际上,通过遍历$result数组中的每个项目,结果中的每个description将成为新对象中的自己的属性。每个description属性的内部都会包含idsumcompleted_pct_completed等子项。它将如下所示:

stdClass Object
(
[dev1] => stdClass Object
    (
        [id] => Array
            (
                [0] => 182
                [1] => 218
                [2] => 218
                [3] => 021
                [4] => 186
                [5] => 287
                [6] => 21A
            )

        [sum] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
        [completed_pct_completed] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
        [completed_pct_1msec] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
            .........

    )

[dev1.1] => stdClass Object
    (
        [id] => Array
            (
                [0] => 182
                [1] => 329
                [2] => 465
                [3] => 685
                [4] => 686
                [5] => 607
                [6] => 61A
            )

        [sum] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
        [completed_pct_completed] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
        [completed_pct_1msec] => Array
            (
                [0] => 567
                [1] => 567
                [2] => 567
                [3] => 567
                [4] => 567
                [5] => 567
                [6] => 567
            )
         ............
       )
       ............

到目前为止我做了什么

所以,到目前为止,我是如何构建我想要的:

我创建了一个具有每个唯一描述属性的对象:

$object = new STDClass();
//$flipped is the transposed version of $result, then I got unique names
foreach (array_unique($flipped['description']) as $string)
    $object->{$string} = array();

这完全没问题。然后,我将子项添加到$object

中的每个描述属性
$dummyObject = new STDClass();
foreach ($object as $objectKey=>$objectValue) {
    foreach ($result[0] as $key=>$value){
        if ($key!='description'){
            $dummyObject->{$key}=array();
            $object->$objectKey=$dummyObject;
        }
    }
}

这也很顺利。

这里的问题是将数据插入每个idsummary等等。这就是我所做的:

//add data to the subitems
//foreach dev1.x => array
foreach ($object as $key => $nextObject)
{
    //foreach array as subitems(id, board, etc.) => array
    foreach ($nextObject as $nextKey => $dataArray)
    {
        $dummyArray = array();
        foreach ($result as $array)
        {
            foreach ($array as $arrayKey => $arrayValue)
            {
                if ($array->{'description'} == $key) {
                    if ($nextKey == $arrayKey) {
                        $dummyArray[]=$arrayValue;
                    }
                }
            }
        }
        $object->{$key}->{$nextKey} = $dummyArray;
    }
}

最后,来自最后dev1.x属性的所有数据最终都被覆盖到每个dev1.x属性中。我尝试在多个地方添加break;,希望我能够推断出出现了什么问题。我有一种强烈的感觉,我发现foreach语句比我知道的更多。有人会介意帮我这个吗?

由于

2 个答案:

答案 0 :(得分:1)

看起来它可能不像看起来那么复杂。除非我误解了转换应该是什么,否则你可以这样做:

foreach ($result as $obj) {
    foreach ($obj as $key => $value) {
        if ($key != 'description') {
            $new_result->{$obj->description}->$key[] = $value;
        }
    }
}

这应该创建对象并一次添加适当的属性和值。

您获得重复的原因在于此部分:

$dummyObject = new STDClass();
foreach ($object as $objectKey=>$objectValue) {
    foreach ($result[0] as $key=>$value){
        if ($key!='description'){
            $dummyObject->{$key}=array();
            $object->$objectKey=$dummyObject;
        }
    }
}

当您执行$object->$objectKey=$dummyObject;因为您在循环之前创建了对象时,您正在重置并将同一个对象重新分配给每个$objectKey。因此,当您稍后填写值时,您最终会得到最后一个的多个副本。如果您使用对象的副本($object->$objectKey= clone $dummyObject;),它应该可以工作。但它似乎有点过于复杂。

答案 1 :(得分:0)

只需在迭代时创建键:

$data = new stdClass();
foreach ($result as $object) {
    $description = $object->description;
    isset($data->{$description}) or $data->{$description} = new stdClass();

    foreach ($object as $name => $value) {
        if ($name === 'description') { continue; }
        $data->{$description}->{$name}[] = $value;
    }
}

我不喜欢将字段描述为字段名称。访问$data->{'dev1.1'}很难看。将它打包到一个对象数组中,但description属性只是一个字符串,其他属性将是聚合数组。它需要对程序进行一些修改(可靠的描述索引)。