parser

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

 

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

Ответ

virusav 26.05.2015 16:45

Не стал приводить код сразу, т.к. оба варианта не оптимизированы.
Комментарий приводится относительно другого метода.
Сравнивание шло по $status:memory.used.
Второй вариант писался для сравнения, поэтому в нем есть не все, что реализовано в первом.
Вариант 1:
1. Потребляет меньше ресурсов, если в значениях ключей первых уровней много повторяющихся значений.
2. Есть подсчет количества записей по уровням хеша.
3. Можно задать значения полей для разных уровней хеша, чтобы можно было получить данные без обращения к самому последнему уроню хеша (таблица).
@getHashOfHash[hInput][hResult;tKey;bField;tField;hField]
	^if(!^hInput.contains[iKey]){
		$hResult[^hash::create[]]
		$hResult.[$hInput.hLevel.1.key][^getHashOfHash[
			$.tData[$hInput.tData]
			$.hLevel[$hInput.hLevel]
			$.iKey(1)
		]]
	}{
		$hResult[^hInput.tData.hash[$hInput.hLevel.[$hInput.iKey].key][$hHASH_TABLE_PARAM]]
		$tKey[^hResult._keys[]]
		$bField(^hInput.hLevel.contains[$hInput.iKey] && ^hInput.hLevel.[$hInput.iKey].contains[field])
		^if($bField){
			$tField[^hInput.hLevel.[$hInput.iKey].field.split[,;;name]]
		}
		^hInput.iKey.inc[]
		^if(^hInput.hLevel.contains[$hInput.iKey]){
			^tKey.menu{
				^if($bField){
					$hField[^tField.menu{
						$.[$tField.name][$hResult.[$tKey.key].[$tField.name]]
					}]
				}
				$hResult.[$tKey.key][
					$.[$hInput.hLevel.[$hInput.iKey].key][^getHashOfHash[
						$.tData[$hResult.[$tKey.key]]
						$.hLevel[$hInput.hLevel]
						$.iKey($hInput.iKey)
					]]
				]
				^if($bField){
					^hResult.[$tKey.key].add[$hField]
				}
				$hResult.[$tKey.key].data_count($hResult.[$tKey.key].data_count+$hResult.[$tKey.key].[$hInput.hLevel.[$hInput.iKey].key].data_count)
				$hResult.data_count($hResult.data_count+$hResult.[$tKey.key].[$hInput.hLevel.[$hInput.iKey].key].data_count)
			}
		}{
			^hInput.iKey.dec[]
			$tKey[^hResult._keys[]]
			^tKey.menu{
				$hResult.data_count($hResult.data_count+^hResult.[$tKey.key].count[])
			}
		}
	}
	$result[$hResult]
Вариант 2:
1. Потребляет меньше ресурсов, если в значениях ключей первых уровней много разных значений.
@getHashOfHash[hInput][hResult;iKeyLast;hTemp;key;value]
	$hResult[^hash::create[]]
	$iKeyLast(^hInput.hLevel._count[])
	^hInput.tData.menu{
		$hTemp[$hResult]
		^hInput.hLevel.foreach[key;value]{
			^if(!^hTemp.contains[$value.key]){
				$hTemp.[$value.key][^hash::create[]]
			}
			^if($key<$iKeyLast){
				^if(!^hTemp.[$value.key].contains[$hInput.tData.[$value.key]]){
					$hTemp.[$value.key].[$hInput.tData.[$value.key]][^hash::create[]]
				}
			}(!^hTemp.[$value.key].contains[$hInput.tData.[$value.key]]){
				$hTemp.[$value.key].[$hInput.tData.[$value.key]][^table::create[$hInput.tData;
					$.offset(^hInput.tData.offset[])
					$.limit(1)
				]]
			}{
				^hTemp.[$value.key].[$hInput.tData.[$value.key]].join[$hInput.tData;
					$.offset(^hInput.tData.offset[])
					$.limit(1)
				]
			}
			$hTemp[$hTemp.[$value.key].[$hInput.tData.[$value.key]]]
		}
	}
	$result[$hResult]