parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

Ответ

Misha v.3 12.03.2011 02:17 / 12.03.2011 02:22

ваша задача всё равно не является той задачей, для которой действительно требуется применение хэша. попробую проиллюстрировать его использование на задаче вывода сообщения с тэгами.

сообщения, выводимые на страницы, находятся в таблице $tMessage (id, content) (это может быть и хэш, но мне, ввиду однородности данных, больше нравится таблица). теги -- в таблице $tTag (id, name).

а в таблице $tMessageToTag хранятся связи (message_id, tag_id). можно сразу доставать эти связи в виде хэша, но в этой демонстрации я буду использовать эти данные разными способами, поэтому для удобства демонстрации они в таблице.

для начала на основании таблицы $tMessageToTag формируем такой хэш:
$hMessageToTag[
	$.1[
		$.5(1)
		$.10(1)
		$.15(1)
	]
	$.2[
		$.5(1)
		$.6(1)
	]
	...
]
тут ключ первого уровня -- message_id, ключ второго -- tag_id. значение -- просто чтоб было (можно с пустыми значениями, но тогда проверка ниже будет немного другой).

далее так:
^tMessage.menu{
	<p>$tMessage.content</p>
	^tTag.menu{^if($hMessageToTag.[$tMessage.id].[$tTag.id]){<span>$tTag.name</span>}}[, ]
}
кстати подобную структуру в хэше бывает очень неудобно получать на основе данных, которые достаются из БД, поэтому иногда структуру хеша делают иной (с составным ключом):
$hMessageToTag[
	$.1=5(1)
	$.1=10(1)
	$.1=15(1)
	$.2=5(1)
	$.2=6(1)
	...
]
тут первая часть ключа (до разделителя, который я выбрал в виде символа '=') -- message_id, вторая часть -- tag_id.
подобный "плоский" хэш может быть получен из таблицы, полученной из БД с помощью единственной команды (будет получен хэш в котором более сложные значения, но на работоспособность подхода это не влияет):
$hMessageToTag[^tMessageToTag.hash{$tMessageToTag.message_id=$tMessageToTag.tag_id}]
код проверки наличия у сообщения определённого тэга меняется на следующий:
^if($hMessageToTag.[$tMessage.id=$tTag.id]){...}
но приведённый выше подход в общем случае плох. проблема в том, что у нас есть вложенный цикл с проверкой. если тэгов существенно больше, чем привязок, то внутренний цикл будет крутиться вхолостую, поэтому для устранения повторяющегося внутреннего холостого цикла лучше сделать хэш таблиц с ключами message_id, а структуру с тэгами перевести в хэш (или сразу доставать из БД как хэш):
$hMessageTags[^tMessageToTag.hash[message_id][$.type[table] $.distinct(true)]]
$hTag[^tTag.hash[tag_id]]

^tMessage.menu{
	<p>$tMessage.content</p>
	^if($hMessageTags.[$tMessage.id]){
		^hMessageTags.[$tMessage.id].menu{
			<span>$hTag.[$hMessageTags.[$tMessage.id].tag_id].name</span>
		}[, ]
	}
}
в $hMessageTags будет следующая структура (ключами являются message_id, а значениями -- таблицы):
$hMessageTags[
	$.1[^table::create{message_id	tag_id
1	5
1	10
1	15}]

	$.2[^table::create{message_id	tag_id
2	5
2	6}]
]
P.S. приводимый код я не проверял и в нём возможны синтаксические или иные ошибки.