gpt4 book ai didi

php - 确定哪些对象链接或不链接到主根对象

转载 作者:IT王子 更新时间:2023-10-28 23:52:11 25 4
gpt4 key购买 nike

我正在尝试浏览一堆带有指向其他对象的链接的对象。我想从最低的 id 号(根对象)开始,并根据连接的链接浏览每个对象。一些对象链接会循环回到以前的对象,所以我想确保每个对象只查看一次,否则我会陷入无限循环。我还希望能够通过浏览从第一个链接开始的链接来判断哪些对象无法访问。

我的数据库中的表如下所示:

对象表:

+----+---------+
| id | title |
+----+---------+
| 1 | Apple |
| 3 | Carrot |
| 4 | Dill |
| 5 | Egg |
| 6 | Fred |
| 7 | Goat |
| 8 | Harry |
| 9 | Igloo |
| 10 | Jason |
| 11 | Klaus |
| 12 | Banana |
| 15 | Oyster1 |
| 16 | Oyster2 |
+----+---------+

Object_Links 表:

+----+---------+--------------+
| id | obj_id | obj_link_id |
+----+---------+--------------+
| 1 | 1 | 12 |
| 2 | 1 | 5 |
| 3 | 3 | 1 |
| 4 | 3 | 12 |
| 5 | 3 | 3 |
| 6 | 4 | 1 |
| 7 | 4 | 5 |
| 8 | 5 | 6 |
| 9 | 6 | 7 |
| 10 | 7 | 7 |
| 11 | 7 | 8 |
| 12 | 9 | 12 |
| 13 | 9 | 5 |
| 14 | 10 | 1 |
| 15 | 10 | 5 |
| 16 | 10 | 8 |
| 17 | 11 | 1 |
| 18 | 11 | 5 |
| 19 | 11 | 10 |
| 20 | 12 | 3 |
| 21 | 15 | 16 |
| 22 | 16 | 15 |
+----+---------+--------------+

因此,从表中您可以看到对象 1 具有指向对象 12 和 5 的链接。

我的 SQL 查询如下所示:

select  object.id, title, obj_link_id
from object
left join object_links ON object.id = object_links.object_id
order by object.id

给出表格:

+----+---------+--------------+
| id | title | obj_link_id |
+----+---------+--------------+
| 1 | Apple | 12 |
| 1 | Apple | 5 |
| 3 | Carrot | 1 |
| 3 | Carrot | 12 |
| 3 | Carrot | 3 |
| 4 | Dill | 1 |
| 4 | Dill | 5 |
| 5 | Egg | 6 |
| 6 | Fred | 7 |
| 7 | Goat | 7 |
| 7 | Goat | 8 |
| 8 | Harry | NULL |
| 9 | Igloo | 12 |
| 9 | Igloo | 5 |
| 10 | Jason | 1 |
| 10 | Jason | 5 |
| 10 | Jason | 8 |
| 11 | Klaus | 1 |
| 11 | Klaus | 5 |
| 11 | Klaus | 10 |
| 12 | Banana | 3 |
| 15 | Oyster1 | 16 |
| 16 | Oyster2 | 15 |
+----+---------+--------------+

在我使用的 PHP 中:

$objects = $stmt->fetchAll(PDO::FETCH_CLASS);

我不确定是否有更好的方法来获取这些用于我的目的,因此欢迎提出建议。

一个 print_r($objects) 产生:

Array
(
[0] => stdClass Object
(
[id] => 1
[title] => Apple
[obj_link_id] => 12
)

[1] => stdClass Object
(
[id] => 1
[title] => Apple
[obj_link_id] => 5
)

[2] => stdClass Object
(
[id] => 3
[title] => Carrot
[obj_link_id] => 1
)

[3] => stdClass Object
(
[id] => 3
[title] => Carrot
[obj_link_id] => 12
)

[4] => stdClass Object
(
[id] => 3
[title] => Carrot
[obj_link_id] => 3
)

[5] => stdClass Object
(
[id] => 4
[title] => Dill
[obj_link_id] => 1
)

[6] => stdClass Object
(
[id] => 4
[title] => Dill
[obj_link_id] => 5
)

[7] => stdClass Object
(
[id] => 5
[title] => Egg
[obj_link_id] => 6
)

[8] => stdClass Object
(
[id] => 6
[title] => Fred
[obj_link_id] => 7
)

[9] => stdClass Object
(
[id] => 7
[title] => Goat
[obj_link_id] => 7
)

[10] => stdClass Object
(
[id] => 7
[title] => Goat
[obj_link_id] => 8
)

[11] => stdClass Object
(
[id] => 8
[title] => Harry
[obj_link_id] =>
)

[12] => stdClass Object
(
[id] => 9
[title] => Igloo
[obj_link_id] => 12
)

[13] => stdClass Object
(
[id] => 9
[title] => Igloo
[obj_link_id] => 5
)

[14] => stdClass Object
(
[id] => 10
[title] => Jason
[obj_link_id] => 1
)

[15] => stdClass Object
(
[id] => 10
[title] => Jason
[obj_link_id] => 5
)

[16] => stdClass Object
(
[id] => 10
[title] => Jason
[obj_link_id] => 8
)

[17] => stdClass Object
(
[id] => 11
[title] => Klaus
[obj_link_id] => 1
)

[18] => stdClass Object
(
[id] => 11
[title] => Klaus
[obj_link_id] => 5
)

[19] => stdClass Object
(
[id] => 11
[title] => Klaus
[obj_link_id] => 10
)

[20] => stdClass Object
(
[id] => 12
[title] => Banana
[obj_link_id] => 3
)

[21] => stdClass Object
(
[id] => 15
[title] => Oyster1
[obj_link_id] => 16
)

[22] => stdClass Object
(
[id] => 16
[title] => Oyster2
[obj_link_id] => 15
)

)

请注意,括号中的数字只是数组索引,而不是对象ID号,所以不要让索引把你弄丢了。

我正在尝试找到一种方法来确定哪些是链接对象,哪些是未链接对象。根据上述情况,对象应按如下方式分离:

**Linked:**

Apple
Banana
Carrot
Egg
Fred
Goat
Harry

**Not Linked:**

Dill
Igloo
Jason
Klaus
Oyster1
Oyster2

我的主要问题:

如何在 PHP 中创建一个循环来遍历这样的结构,尤其是当每个对象可以有多个链接时?最终,我想生成两个对象集合,一个包含链接对象,一个包含未链接对象。示例集合可能如下所示:

stdClass Object
(
[LinkedElements] => stdClass Object
(
[1] => stdClass Object
(
[id] => 1
[name] => Apple
[link] => Array
(
[0] => 14
[1] => 5
)

)

[14] => stdClass Object
(
[id] => 14
[name] => Banana
[link] => Array
(
[0] => 3
)

)

[3] => stdClass Object
(
[id] => 3
[name] => Carrot
[link] => Array
(
[0] => 1
[1] => 14
[2] => 3
)

)

[5] => stdClass Object
(
[id] => 5
[name] => Egg
[link] => Array
(
[0] => 6
)

)

[6] => stdClass Object
(
[id] => 6
[name] => Fred
[link] => Array
(
[0] => 7
)

)

[7] => stdClass Object
(
[id] => 7
[name] => Goat
[link] => Array
(
[0] => 7
[1] => 8
)

)

[8] => stdClass Object
(
[id] => 8
[name] => Harry
)

)

[UnLinkedElements] => stdClass Object
(
[4] => stdClass Object
(
[id] => 4
[name] => Dill
[link] => Array
(
[0] => 1
[1] => 5
)

)

[9] => stdClass Object
(
[id] => 9
[name] => Igloo
[link] => Array
(
[0] => 14
[1] => 5
)

)

[10] => stdClass Object
(
[id] => 10
[name] => Jason
[link] => Array
(
[0] => 1
[1] => 5
[2] => 8
)

)

[11] => stdClass Object
(
[id] => 11
[name] => Klaus
[link] => Array
(
[0] => 1
[1] => 5
[2] => 10
)

)

[15] => stdClass Object
(
[id] => 15
[name] => Oyster1
[link] => Array
(
[0] => 16
)

)

[16] => stdClass Object
(
[id] => 16
[name] => Oyster2
[link] => Array
(
[0] => 15
)

)

)

)

请注意:

  • 导航是从对象到链接完成的,而不是相反。
  • 可以让一个对象指向它自己(就像对象 7 一样)。
  • 上述示例结构(在我的主要问题下方)只是一个建议,我愿意接受其他建议。
  • 免责声明:此问题基于另一个问题 I previously asked .在我最初的问题中,我手动创建了测试对象,但我无法以这种方式将它们从我的数据库中拉出。

最佳答案

将数据作为两个单独的数组进行处理会更容易(恕我直言)。一组对象及其链接。此外,作为第一部分,我将对象转换为以 ID 作为键,这样我就可以直接使用它,而不必每次都搜索 ID。

另外,为了使解决方案更简单,我在访问它时在对象数组中创建了一个标志,这样当我尝试再次引用它时,我可以检查它是否已经被访问过。

<?php 
error_reporting ( E_ALL );
ini_set ( 'display_errors', 1 );

$objects =[[1,'apple'],
[3, 'Carrot'],
[4, 'Dill'],
[5, 'Egg '],
[6, 'Fred'],
[7, 'Goat'],
[8, 'Harry'],
[9, 'Igloo'],
[10, 'Jason'],
[11, 'Klaus'],
[12, 'Banana'],
[15, 'Oyster1'],
[16, 'Oyster2' ]];
$links =[[1,12],
[1,5],
[3,1],
[3,12],
[3,3],
[4,1],
[4,5],
[5,6],
[6,7],
[7,7],
[7,8],
[8,null],
[9,12],
[9,5],
[10,1],
[10,5],
[10,8],
[11,1],
[11,5],
[11,10],
[12,3],
[15,16],
[16,15 ]];

function buildTree ( $id, &$objects, $links ) {
foreach ( $links as $testNode ) {
if ( $testNode[0] == $id &&
$testNode[1] != $id &&
$testNode[1] != null &&
!isset($objects[$testNode[1]]['visited']) ) {
$objects[$testNode[1]]['visited'] = true;
buildTree ( $testNode[1], $objects, $links);
}
}
}

// Convert array to have the ID as key
$objects = array_combine(array_column($objects, 0), $objects);
// Fetch ID of first item
reset($objects);
$startID = key($objects);
// Mark as visited
$objects[$startID]['visited'] = true;
// Process
buildTree ( $startID, $objects, $links);

$linked = [];
$notLinked = [];
foreach ( $objects as $object) {
if ( isset($object['visited']) ) {
$linked[] = $object[1];
}
else {
$notLinked[] = $object[1];
}
}
echo "Linked...".PHP_EOL;
print_r($linked);

echo "Not linked...".PHP_EOL;
print_r($notLinked);

如你所见,核心是递归的buildTree函数。这使用 &$objects 因为这意味着对该函数的所有调用都将使用相同的数组。因为我想建立项目的所有用途,所以这很重要。

buildTree中的条件,检查是否是我们想要的节点,它不是指同一个节点(浪费时间再找),不是null(不知道为什么链接到null,但又不值得看任何进一步)并且该节点尚未被访问过。如果这些条件都OK,它将下一个节点标记为已访问并进入下一个级别。

输出是...

Linked...
Array
(
[0] => apple
[1] => Carrot
[2] => Egg
[3] => Fred
[4] => Goat
[5] => Harry
[6] => Banana
)
Not linked...
Array
(
[0] => Dill
[1] => Igloo
[2] => Jason
[3] => Klaus
[4] => Oyster1
[5] => Oyster2
)

关于php - 确定哪些对象链接或不链接到主根对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45974744/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com