Гость
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / PHP - запутался со ссылками / 4 сообщений из 4, страница 1 из 1
08.02.2022, 16:16
    #40132569
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP - запутался со ссылками
Что-то не соображу, где ошибка.

Нужно сформировать из текста иерархическую структуру.
Иерархия строится по отступам (пробелам) в тексте.

Написал такой код:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
function tree_init($data)
{
	if (!isset($data)) return;
	if (!is_array($data)) $data = explode("\n", $data);
	$tree = null;
	$stack = null;
	foreach ($data as $line)
	{
		$lvl = strlen($line) - strlen(ltrim($line, ' '));
		$line = trim($line);
		if (!$line) continue;
		list($code,$name) = explode(' ', $line, 2);
		if (!$code) continue;
		if ($lvl == 0) {
			$stack = [];
			$tree = [];
			$ref = &$tree;
		} else {
			if ($lvl == count($stack)) {
				null;
			} elseif ($lvl < count($stack)) {
				while (count($stack) > $lvl) array_pop($stack);
				$ref = $stack[$lvl-1];
			} else {
				$stack[] = &$ref;
				$ref = &$ref['list'];
			}
		}
		$ref = ['code'=>$code, 'name'=>$name, 'cnt'=>0, 'list'=>[]];
	}
	return $tree;
}

$tree = <<<TEXT
root Перечень
 ??? Прочее
 tie 0.Узлы связи
  core 0.Опорные
  dist 1.Агрегация
  node 2.Доступ
  knot 3.Муфты
  clnt 4.Клиенты
 trc 1.Линии воздушные
  knot 0.Опоры
  bone 1.Магистрали
  leaf 2.Отводы
  pwrl 8.PoE
 lnk 2.Линии подземные
  knot 0.Колодцы
  bone 1.Магистрали
  leaf 2.Отводы
 obj 3.Объекты
  cmrc ТЦ
 cam 4.Камеры
  site 0.Камеры
  area 1.Зоны
 tag 8.Информация
  excl 0.Важное
  info 1.Подробности
  temp 9.Временное
 prj 9.Проекты
  site 0.Сооружения
  line 1.Линии
  temp 9.Временное
TEXT;
$tree = tree_init($tree);
print_r($tree);


Но результат получается неправильный, в полученной иерархии нет возврата назад.
Если записать так: $ref = &$stack[$lvl-1]
то результат тоже неправильный, предшествующая структура не сохраняется.
...
Рейтинг: 0 / 0
08.02.2022, 16:51
    #40132587
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP - запутался со ссылками
Вот так получается лучше.
Но почему-то остается только один дочерний узел.
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
function tree_init($data)
{
	if (!isset($data)) return;
	if (!is_array($data)) $data = explode("\n", $data);
	$tree = null;
	$stack = null;
	foreach ($data as $line)
	{
		$lvl = strlen($line) - strlen(ltrim($line, ' '));
		$line = trim($line);
		if (!$line) continue;
		list($code,$name) = explode(' ', $line, 2);
		if (!$code) continue;
		if ($lvl == 0) {
			$tree = ['_code'=>$code, '_name'=>$name, '_cnt'=>0];
			$stack = [];
			$ref = & $tree;
			continue;
		} else {
			if ($lvl == count($stack)) {
				null;
			} elseif ($lvl < count($stack)) {
				while (count($stack) > $lvl) array_pop($stack);
				if (!array_key_exists($code, $stack[$lvl-1]))$stack[$lvl-1][$code] = [];
				$ref = & $stack[$lvl-1][$code];
			} else {
				$stack[] = & $ref;
				if (!array_key_exists($code, $ref)) $ref[$code] = [];
				$ref = & $ref[$code];
			}
		}
		$ref['_code'] = $code;
		$ref['_name'] = $name;
		$ref['_cnt'] = 0;
	}
	return $tree;
}
...
Рейтинг: 0 / 0
08.02.2022, 18:02
    #40132613
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP - запутался со ссылками
Сделал так:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
function tree_init($data)
{
	if (!isset($data)) return;
	if (!is_array($data)) $data = explode("\n", $data);
	$tree = null;
	foreach ($data as $line)
	{
		$lvl = strlen($line) - strlen(ltrim($line, ' '));
		$line = trim($line);
		if (!$line) continue;
		list($code,$name) = explode(' ', $line, 2);
		if (!$code) continue;
		if ($lvl == 0) {
			unset($tree);
			$tree = [];
			$stack = [];
		} else {
			if ($lvl == count($stack)) {
				$tree = $stack[$lvl-1];
				if (!array_key_exists($code, $tree)) $tree[$code] = [];
				$tree = &$tree[$code];
			} elseif ($lvl < count($stack)) {
				while (count($stack) > $lvl+1) array_pop($stack);
				$tree = array_pop($stack);
				if (!array_key_exists($code, $tree)) $tree[$code] = [];
				$tree = &$tree[$code];
			} else {
				$stack[] = &$tree;
				if (!array_key_exists($code, $tree)) $tree[$code] = [];
				$tree = &$tree[$code];
			}
		}
print "$lvl $code "; foreach ($stack as $s) print ">{$s['_code']}"; print "\n";
		$tree['_code'] = $code;
		$tree['_name'] = $name;
		$tree['_cnt'] = 0;
	}
	return $tree;
}


В отладочном выводе содержимое стека правильное.
Но в результате почему-то только последнее значение.
...
Рейтинг: 0 / 0
08.02.2022, 19:05
    #40132631
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP - запутался со ссылками
Вот так работает правильно:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
function tree_init($data)
{
	if (!isset($data)) return;
	if (!is_array($data)) $data = explode("\n", $data);
	$tree = null;
	foreach ($data as $line)
	{
		$lvl = strlen($line) - strlen(ltrim($line, ' '));
		$line = trim($line);
		if (!$line) continue;
		list($code,$name) = explode(' ', $line, 2);
		if (!$code) continue;
		if ($lvl == 0) {
			unset($tree);
			$tree = [];
			$stack = [];
			$root = &$tree;
		} else {
			if ($lvl == count($stack)) {
				unset($ref); $ref = &$stack[$lvl-1];
				if (!array_key_exists($code, $ref)) $ref[$code] = [];
				unset($tree); $tree = &$ref[$code];
			} elseif ($lvl < count($stack)) {
				unset($ref); $ref = &$stack[$lvl-1];
				while (count($stack) > $lvl) array_pop($stack);
				if (!array_key_exists($code, $ref)) $ref[$code] = [];
				unset($tree); $tree = &$ref[$code];
			} else {
				$stack[] = &$tree;
				unset($ref); $ref = &$tree;
				if (!array_key_exists($code, $ref)) $ref[$code] = [];
				unset($tree); $tree = &$ref[$code];
			}
		}
		$tree['_code'] = $code;
		$tree['_name'] = $name;
		$tree['_cnt'] = 0;
	}
	return $root;
}



Но хотелось бы без обходных маневров с unset и вспомогательной переменной.
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / PHP - запутался со ссылками / 4 сообщений из 4, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]