php通过关联数组解析

发布于 2025-01-14 07:54:50 字数 1556 浏览 1 评论 0原文

我正在尝试生成已安装在机架中的设备的动态列表。假设我有以下 mysql 数据:

ID    Name          Order  Owner Units
--------------------------------------
56    9U Rackmount  0      0     9.0
54    Rackmount     8      56    1.2
 9    RPi 4 B       2      59    0.1
 7    MacMini B     2      54    0.1
32    Router        1      56    1.0
14    RPi 4 C2      4      59    0.1
33    Switch A      2      56    1.0
35    POE Switch    3      56    1.0
 8    RPi 4 A       1      59    0.1
13    RPi 4 C1      3      59    0.1
59    Rackmount     4      56    1.4
28    Powerstrip    5      56    1.0
38    Switch B      6      56    1.0

我想通过关联数组(可能使用 $order 作为键)生成列表(如下)?单位列可以帮助描述设备将占用多少个单位;整数是垂直的,而小数值是水平单位:

9U Rackmount [56]
--------------------------
1:    Router [32]
2:    Switch A [33]
3:    POE Switch [35]
4:    Rackmount [59]
        1:  RPi 4 A [8]
        2:  RPi 4 B [9]
        3:  RPi 4 C1 [13]
        4:  RPi 4 C2 [14]
5:    Powerstrip [28]
6:    Switch B [38]
7:    (empty)
8:    Rackmount [54]
        1:  (empty)
        2:  MacMini B [7]
9:    (empty)

这是我想出的(递归函数),但它甚至没有生成正确的顺序..

function tree_build ($item) {
    $found = array(); $branch = array();
    $branch = get_children_via_owner($item);
    $order = get_placement_within_owner($item);
    if (count($branch) > 0) {
        foreach ($branch as $twig) { $found[] = tree_build($twig); }
    } else {
        return(array($order => $item))
    }
    return(array(array($order => $item), $found));
}

有什么想法吗?

I'm trying to generate a dynamic list of devices I have installed in a rackmount. Let's say I have the following mysql data:

ID    Name          Order  Owner Units
--------------------------------------
56    9U Rackmount  0      0     9.0
54    Rackmount     8      56    1.2
 9    RPi 4 B       2      59    0.1
 7    MacMini B     2      54    0.1
32    Router        1      56    1.0
14    RPi 4 C2      4      59    0.1
33    Switch A      2      56    1.0
35    POE Switch    3      56    1.0
 8    RPi 4 A       1      59    0.1
13    RPi 4 C1      3      59    0.1
59    Rackmount     4      56    1.4
28    Powerstrip    5      56    1.0
38    Switch B      6      56    1.0

I'd like to generate the list (below) via an associative array (potentially using $order as a key)? The Units column can help describe how many units the device will occupy; whole numbers are vertical while decimal values are horizontal units:

9U Rackmount [56]
--------------------------
1:    Router [32]
2:    Switch A [33]
3:    POE Switch [35]
4:    Rackmount [59]
        1:  RPi 4 A [8]
        2:  RPi 4 B [9]
        3:  RPi 4 C1 [13]
        4:  RPi 4 C2 [14]
5:    Powerstrip [28]
6:    Switch B [38]
7:    (empty)
8:    Rackmount [54]
        1:  (empty)
        2:  MacMini B [7]
9:    (empty)

This is what I came up with (recursive function), but it's not generating even the correct order..

function tree_build ($item) {
    $found = array(); $branch = array();
    $branch = get_children_via_owner($item);
    $order = get_placement_within_owner($item);
    if (count($branch) > 0) {
        foreach ($branch as $twig) { $found[] = tree_build($twig); }
    } else {
        return(array($order => $item))
    }
    return(array(array($order => $item), $found));
}

Any ideas?

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

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

发布评论

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

评论(1

喜爱皱眉﹌ 2025-01-21 07:54:50

是的,递归函数的方向是正确的,但您没有显示 get_children_via_ownerget_placement_within_ownertree_build 正在做什么,而且还有没有排序,它似乎没有考虑空元素。

递归函数应该做 3 件事:

  • 搜索初始数组以查找所有具有您正在评估的父级的
  • 数组根据 Order 对数组进行排序
  • 将缺失值添加为空槽

这是它在代码中的样子:

function buildTree(int $Owner = 0) {
    global $racks;
    $ret = [];
    foreach ($racks as $id => $rack) {
        if ($rack['Owner'] != $Owner) { // Exclude elements with different parent
            continue;
        }
        $rack['slots'] = buildTree($id); // Recursive
        ksort($rack['slots']); // Sort based on Order
        if (sizeof($rack['slots'])) {
            $max_order = array_key_last($rack['slots']); 
            for ($i = 1; $i <= $max_order; $i++) { // Fill empty slots
                if (!isset($rack['slots'][$i])) {
                    $rack['slots'][] = ['Name' => '(empty)', 'ID' => 0, 'Order' => $i, 'Units' => 0];
                }
            }
            usort($rack['slots'], function ($a, $b) {
                return $b['Order'] < $a['Order'];
            });
        }
        $ret[$rack['Order']] = $rack; // User Order as array key for easy sorting
    }
    return $ret;
}

然后对于打印,您还可以编写一个递归函数,但考虑到您为每个级别使用非常不同的样式,如果您确定只有 3 个级别,那么执行嵌套 foreach 可能会更容易,如下所示。

foreach ($tree as $rack) {
    echo $rack['Name'].' ['.$rack['ID'].']'.PHP_EOL;
    echo "---------".PHP_EOL;
    if (!empty($rack['slots']) && sizeof($rack['slots'])) {
        foreach ($rack['slots'] as $sub1) {
            echo $sub1['Order'].":    ".$sub1['Name'].' ['.$sub1['ID'].']'.PHP_EOL;
            if (!empty($sub1['slots']) && sizeof($sub1['slots'])) {
                foreach ($sub1['slots'] as $sub2) {
                    echo "        ".$sub2['Order'].":  ".$sub2['Name'].' ['.$sub2['ID'].']'.PHP_EOL;
                }
            }
        }
    }
}

最终的输出正是您正在寻找的,除了最后一个空插槽,我认为您没有足够的数据来确定机架末端有一个空插槽。

9U Rackmount [56]
---------
1:    Router [32]
2:    Switch A [33]
3:    POE Switch [35]
4:    Rackmount [59]
        1:  RPi 4 A [8]
        2:  RPi 4 B [9]
        3:  RPi 4 C1 [13]
        4:  RPi 4 C2 [14]
5:    Powerstrip [28]
6:    Switch B [38]
7:    (empty) [0]
8:    Rackmount [54]
        1:  (empty) [0]
        2:  MacMini B [7]

作为参考,这就是生成初始数组的方式

$tree = buildTree();

这是初始查询

$query = 'SELECT * FROM racks ORDER BY `Owner`';
$racks = [];
if ($stmt = $sql_connection->prepare($query)) {
    $stmt->execute();
    $result = $stmt->get_result();
    while ($data = $result->fetch_assoc()) {
        $racks[$data['ID']] = $data;
    }
}

Yes, the direction of the recursive function was correct, but you're not showing what get_children_via_owner, get_placement_within_owner, and tree_build are doing, plus there's no sorting and it doesn't seem to account for empty elements.

The recursive function should do 3 things:

  • search the initial array to find all that have the parent you're evaluating
  • sort the array based on the Order
  • add missing values as empty slots

Here's how it looks like in Code:

function buildTree(int $Owner = 0) {
    global $racks;
    $ret = [];
    foreach ($racks as $id => $rack) {
        if ($rack['Owner'] != $Owner) { // Exclude elements with different parent
            continue;
        }
        $rack['slots'] = buildTree($id); // Recursive
        ksort($rack['slots']); // Sort based on Order
        if (sizeof($rack['slots'])) {
            $max_order = array_key_last($rack['slots']); 
            for ($i = 1; $i <= $max_order; $i++) { // Fill empty slots
                if (!isset($rack['slots'][$i])) {
                    $rack['slots'][] = ['Name' => '(empty)', 'ID' => 0, 'Order' => $i, 'Units' => 0];
                }
            }
            usort($rack['slots'], function ($a, $b) {
                return $b['Order'] < $a['Order'];
            });
        }
        $ret[$rack['Order']] = $rack; // User Order as array key for easy sorting
    }
    return $ret;
}

Then for printing you can also write a recursive function, but considering you use a very different style for each level, if you're sure you only have 3 levels it's probably easier to do a nested foreach, like follows.

foreach ($tree as $rack) {
    echo $rack['Name'].' ['.$rack['ID'].']'.PHP_EOL;
    echo "---------".PHP_EOL;
    if (!empty($rack['slots']) && sizeof($rack['slots'])) {
        foreach ($rack['slots'] as $sub1) {
            echo $sub1['Order'].":    ".$sub1['Name'].' ['.$sub1['ID'].']'.PHP_EOL;
            if (!empty($sub1['slots']) && sizeof($sub1['slots'])) {
                foreach ($sub1['slots'] as $sub2) {
                    echo "        ".$sub2['Order'].":  ".$sub2['Name'].' ['.$sub2['ID'].']'.PHP_EOL;
                }
            }
        }
    }
}

The final output is exactly what you're looking for, apart from the last empty slot, which I don't think you have enough data to determine there's an empty slot at the end of the rack.

9U Rackmount [56]
---------
1:    Router [32]
2:    Switch A [33]
3:    POE Switch [35]
4:    Rackmount [59]
        1:  RPi 4 A [8]
        2:  RPi 4 B [9]
        3:  RPi 4 C1 [13]
        4:  RPi 4 C2 [14]
5:    Powerstrip [28]
6:    Switch B [38]
7:    (empty) [0]
8:    Rackmount [54]
        1:  (empty) [0]
        2:  MacMini B [7]

As a reference, this is how you generate the initial array

$tree = buildTree();

And this is the initial query

$query = 'SELECT * FROM racks ORDER BY `Owner`';
$racks = [];
if ($stmt = $sql_connection->prepare($query)) {
    $stmt->execute();
    $result = $stmt->get_result();
    while ($data = $result->fetch_assoc()) {
        $racks[$data['ID']] = $data;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文