【问题标题】:PHP - Adding children to multi-level associative array by referencePHP - 通过引用将子级添加到多级关联数组
【发布时间】:2016-06-10 15:50:45
【问题描述】:

我有一个来自 MySQL 的记录集,它返回给定对象的类别 ID 及其值。例如:

+-----------+-------------+----------------+
| object_id | category_id | category_value |
+-----------+-------------+----------------+
|         1 |           2 | VEGETARIAN     |
|         1 |           3 | MATARÓ         |
|         1 |           5 | MARCO POLO     |
|         1 |           5 | JOHN DOE       |
|         2 |           2 | VEGETARIAN     |
|         2 |           3 | MATARÓ         |
|         2 |           5 | JOHN DOE       |
+-----------+-------------+----------------+

有了这个,我需要的是 PHP 中的以下结果关联数组:

// They are arrays, so more than one object_id can be in the same category tree (and the object_id can be repeated across categories)

$final_array['VEGETARIAN']['MATARÓ']['MARCO POLO'] = array(1);
$final_array['VEGETARIAN']['MATARÓ']['JOHN DOE'] = array(1, 2);

查询首先按object_id 对结果进行排序,然后再按category_id 和用户设置的顺序对结果进行排序。所以,它就像ORDER BY object_id ASC, FIELD(category_id, usercat1, usercat2, usercat3)(在这种情况下是FIELD(category_id, 2, 3, 5)

我有每组都经过的循环,我试图保留一个临时变量来存储数组级别,因为它们可以更改(并不总是 3 级),所以类似于:

$temporary_array['VEGETARIAN'] = array();
$temporary_array = $temporary_array['VEGETARIAN'];

// And then, on the next iteration
$temporary_array['MATARÓ'] = array();
$temporary_array = $temporary_array['MATARÓ'];
// Now, $temporary_array would be equal to $temporary_array['VEGETARIAN']['MATARÓ'];

所以我可以根据 new 类别值创建一个主键,该值将存储为父数组的子级,并获取所有层次树。 每个级别都应包括所有下一个级别

我尝试全局声明它并通过引用传递它,但它似乎不起作用。

有没有办法在 PHP 中实现这一点?你会怎样做才能得到想要的结果?

编辑:

我更接近于颠倒类别的顺序,所以我首先得到最后一个类别(其中没有其他类别的那个),然后我向上排列数组,如下所示:

// Long story very short, would be like
$final_array['new_category_value'] = $old_final_array; 

并为每个对象继续上升。当我更改object_id 时,我会:

array_merge_recursive($final_array, $actual_object_array);

但是,我仍然无法获得想要的结果。

感谢您的宝贵时间和 cmets!

【问题讨论】:

  • 您使用什么标准来确定一个类别应该是任何其他类别的父级还是子级?它只是升序 category_id 值 - 即 5>3 因此类别 5 应该是类别 3 的子类别,并且 id 为 5 的两个类别应该具有相同的父类别?
  • 这是它们出现的顺序。如果类别 5 出现在 3 之前,则数组应为 $t['category5_value']['category3_value']。当然,如果类别 3 有多个值,则它们都必须是类别 5 的子项。但这只是因为顺序(每个查询都可以更改,因为用户决定它)。

标签: php arrays associative-array multi-level


【解决方案1】:

假设您可以将 SQL 数据作为关联数组访问,并且“1”值是 object_id(而不是说 true/false 0/1 等),如下所示:

$sth = $dbh->prepare("SELECT ......"); //Your SQL Here
$sth->execute();
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);

$rows 应该包含如下内容:

$rows = array(
    array(
        "object_id" => 1,
        "category_id" => 2,
        "category_value" => "VEGETARIAN"
    ),
    array(
        "object_id" => 1,
        "category_id" => 3,
        "category_value" => "MATARÓ"
    ),
    array(
        "object_id" => 1,
        "category_id" => 5,
        "category_value" => "MARCO POLO"
    ),
    array(
        "object_id" => 1,
        "category_id" => 5,
        "category_value" => "JOHN DOE"
    )
); 

从这一点开始,您可以遍历行。单个行发生的情况取决于它之前的行,因此存储并更新包含该行的变量,以便可以在此循环中访问它

//Define your final array
$final_array = array();

//Store a reference to the last row in order to get the last category checked
$lastRow=null;

//Store reference to the last potential parent 
$lastParent=&$final_array;

//Store a reference to the last entry - either an array or the object id
$lastEntry = null;


//Loop over all returned rows
foreach($rows as $row) {

    //If first time around loop, $lastRow will be null
    //If $lastRow is not null, but matches this row's category_id, we should add to the same parent 
    if($lastRow===null || $lastRow['category_id']===$row['category_id']){

        $lastParent[$row['category_value']] = $row['object_id'];

        $lastEntry = &$lastParent[$row['category_value']];

        //Note - Do not change last parent here
    }

    //lastCategoryId does not match this row's category ID and is not null, we must change the 
    //  last entry to be an array and add this entry to it.
    else {
        $lastParent = &$lastEntry;

        $lastParent = array($row['category_value'] => $row['object_id']);

        $lastEntry = &$lastParent[$row['category_value']];
    }


    //Loop complete, update the last row
    $lastRow=$row;
}

您现在可以检查调用 print_r($final_array);,它会返回:

Array
(
    [VEGETARIAN] => Array
        (
            [MATARÓ] => Array
                (
                    [MARCO POLO] => 1
                    [JOHN DOE] => 1
                )

        )

)

【讨论】:

  • 感谢您的回答!但是,它似乎不起作用。首先,我不得不稍微修改一下(因为它们是数组——抱歉没有指定),这意味着$t['VEGETARIAN']['MATARÓ']['MARCO POLO] = array(); 中可以有多个object_id。我已经添加了。但是,当我输入多个类别时,我得到的是 $t['VEGETARIAN']['MATARÓ']['VEGETARIAN']['MATARÓ']['VEGETARIAN']...
  • 你能用一个更大的例子来编辑这个问题吗,这里有两个我认为有点不确定的新问题:1) 具有对象 ID 的行是全部组合在一起还是它们可能交错? 2) 对象 id 都是按数字顺序还是按任何顺序排列的?
  • 另外,您是否希望每个唯一对象 ID 的行数相同?如果不是,您最终可能会得到一个包含对象 ID 和类别名称的数组 - 您如何区分类别名称和对象 ID?
  • 我已经编辑了这个问题,添加了更多示例数据和一种新方法,让我更接近得到它 - 仍然没有运气。如果您需要更多信息,请告诉我。感谢您的帮助!
猜你喜欢
  • 2013-03-29
  • 1970-01-01
  • 2012-04-05
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多