Что нового

Возврат дефолтного значения при ненахождении подстроки в строке.

alex_r

Новичок
Сообщения
4
Репутация
0
Помогите разобраться со следущей задачей. Имеется поток входных данных, в котором идет перечисление свойств нескольких предметов. Проблема в том, что некоторые из этих свойств для некоторых предметов могут опускаться, в этом случае предполагается это свойство принимает дефолтное значение. Каким образом это можно реализовать?

В идеале на выходе должны получится 3 массива - $aName, $aMassa, $aQuantity, все одинаковой размерности. Через регулярные выражения $aQuantity получается размером меньше чем два остальных, т.к. это свойство приведено не для всех предметов. С задачей можно справиться, если добавить дополнительный цикл, как в приведенном коде, но мне кажется это не очень оптимально.

Код:
#include <Array.au3>

$sData = '</ID00001, ~name1",massa="1",q="10",ID00001,~name2",massa="5",q="20",ID00003,~name3",massa="100"/>  ,еще какие то данные, где так же могут встречаться ID0000_i и name_i, но уже не так упорядочено'
;Декларативная часть всегда заканчивается тегом '/>'
;Символ ~ больше нигде, кроме как перед началом name_i не встречается, почему то в моих данных он используется в качестве открывающей кавычки и только в этом месте.
;названия и масса есть для всех предметов, количество не у всех. Где количество отсутствует, подразумевается 1.

$sPatternNames = '(?:~)(.+?)\"'
;$aPatternMassa= '(?:~.+?\",massa=\")(\d*)'
$sPatternMassa = '(?:massa=\")(\d*)'

$aNames = StringRegExp($sData, $sPatternNames, 3)
$aMassa = StringRegExp($sData, $sPatternMassa, 3)
_ArrayDisplay($aNames)
_ArrayDisplay($aMassa)


$sPatternGlobal = '(?:~)(.+?)(?:(?:,ID\d{5})|(?:/>))'

$aGlobal = StringRegExp($sData, $sPatternGlobal, 3)
_ArrayDisplay($aGlobal)


$sPatternQuantity = '(?:q=")(\d*)'
$iZ = UBound($aGlobal)
Dim $aQuantity[$iZ]


For $i = 0 To $iZ - 1
	$aQ = StringRegExp($aGlobal[$i], $sPatternQuantity, 3)
	If UBound($aQ) > 0 Then
		$aQuantity[$i] = $aQ[0]
	Else
		$aQuantity[$i] = 1
	EndIf
Next

_ArrayDisplay($aQuantity)


Еще вопрос. Когда я делаю поиск $aGlobal, я вынужден терять данные об ID, т.к. если искать текст между ID\d{5} ... ID\d{5}, то подстроки находятся через раз. Приходится искать начиная с ~ и до ID следущего предмета. Каким образом это можно исправить, а то тут повезло, что ~ больше нигде не встречается.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
alex_r,
Попробуйте так:
Код:
#include <Array.au3>

$iError = 0
$sMassa_Default = 'Massa_Default'
$sQ_Default = 'Q_Default'

$sData = '</ID00001, ~name1",massa="1",q="10",ID00002,~name2",massa="5",q="20",ID00003,~name3",massa="100",' & _
		'ID00022, ~name17",massa="14",q="10",ID00089,~name25",q="20",ID00241,~name39",massa="180",' & _
		'ID12345, ~name91",massa="651",q="160",ID23456,~name452",massa="985",ID34567,~name653",q="2087"/>' & _
		'  ,еще какие то данные, где так же могут встречаться ID0000_i и name_i, но уже не так упорядочено'

$sSearch = StringRegExpReplace($sData, '(?s).*?</(.*?)/>?.*', '$1')
If @extended <> 1 Then
	MsgBox(16, 'Error', 'Error')
	Exit
EndIf
$aID_Temp = StringRegExp($sSearch, '(ID.*?),', 3)
Dim $aResult[UBound($aID_Temp) + 1][4] = [[UBound($aID_Temp), '<name>', '<massa>', '<q>']]
For $i = 1 To $aResult[0][0]
	If $i < $aResult[0][0] Then
		$sPattern = '.*?' & $aID_Temp[$i - 1] & '(.*?)' & $aID_Temp[$i] & '?.*'
	Else
		$sPattern = '.*?' & $aID_Temp[$i - 1] & '(.*?)$'
	EndIf
	$sTemp = StringRegExpReplace($sData, $sPattern, '$1')
	If @extended <> 1 Then
		$iError = 1
		ExitLoop
	EndIf
	$aResult[$i][0] = $aID_Temp[$i - 1]
	$aResult[$i][1] = StringRegExpReplace($sTemp, '.*?~(.*?)",?.*', '$1')
	If @extended <> 1 Then
		$iError = 2
		ExitLoop
	EndIf
	$aResult[$i][2] = StringRegExpReplace($sTemp, '.*?massa="(.*?)",?.*', '$1')
	If @extended <> 1 Then $aResult[$i][2] = $sMassa_Default
	$aResult[$i][3] = StringRegExpReplace($sTemp, '.*?q="(.*?)",?.*', '$1')
	If @extended <> 1 Then $aResult[$i][3] = $sQ_Default
Next
If Not $iError Then
	_ArrayDisplay($aResult)
Else
	MsgBox(16, 'Error', $iError)
EndIf
 
Автор
alex_r

alex_r

Новичок
Сообщения
4
Репутация
0
Спасибо, похоже как раз то что нужно. Я правильно понял, что не возможно составить поиск по условию такого типа [описание подстроки]-->[требуемая под-подстрока, которую нужно найти в этой подстроке], что бы поиск выдавал массив под-подстрок для каждой существующей подстроки? В смысле, без использования дополнительных циклов?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
alex_r,
Может быть и можно, но у меня не получилось.
 

Redline

AutoIT Гуру
Сообщения
506
Репутация
375
Без циклов еще так можно:
Код:
#include <Array.au3>

$sMassa_Default = 'Massa_Default'
$sQ_Default = 'Q_Default'

$sData = '</ID00001, ~name1",massa="1",q="10",ID00002,~name2",massa="5",q="20",ID00003,~name3",massa="100",' & _
        'ID00022, ~name17",massa="14",q="10",ID00089,~name25",q="20",ID00241,~name39",massa="180",' & _
        'ID12345, ~name91",massa="651",q="160",ID23456,~name452",massa="985",ID34567,~name653",q="2087"/>' & _
        '  ,еще какие то данные, где так же могут встречаться ID0000_i и name_i, но уже не так упорядочено'

$sData = StringRegExpReplace($sData, '(?si)(.*?massa="\d+")(.{1,3})(id\d+.*?)', '$1,q="' & $sQ_Default & '",$3')

$sData = StringRegExpReplace($sData, '(?si)(.*?name\d+")(.{1,3})(q=".*?)', '$1,massa="' & $sMassa_Default & '",$3')

$aTotal = StringRegExp($sData, '(?si)(id\d+).*?(name\d+).*?massa="([^"]+).*?q="([^"]+)', 3)
_ArrayDisplay($aTotal)

$aName = StringRegExp($sData, '(name\d+)', 3)
_ArrayDisplay($aName)

$aMassa = StringRegExp($sData, 'massa="([^"]+)', 3)
_ArrayDisplay($aMassa)

$aQuantity = StringRegExp($sData, 'q="([^"]+)', 3)
_ArrayDisplay($aQuantity)
 
Автор
alex_r

alex_r

Новичок
Сообщения
4
Репутация
0
Круто! Буду разбираться.
 
Верх