7erra 629 Posted September 29, 2017 Hello everyone, I wanted to count the linebreaks "<br/>" inside of another string but couldn't find a way. Example: "My first line<br/>My second line<br/>Third line<br/>you guessed it, fifth line<br/>I lied that was the fourth." should return 4. With toString [10] it would be easier since you could use _lineCount = {_x == 10} count (toArray _string); but not with parts that are longer than one character. Share this post Link to post Share on other sites
code34 248 Posted September 29, 2017 hi could lead to good idea :D https://limpet.net/mbrubeck/2014/08/11/toy-layout-engine-2.html Share this post Link to post Share on other sites
Muzzleflash 111 Posted September 29, 2017 How about this (untested): CountNonOverlappingOccurrences = { params ["_array","_pattern"]; private _patternSize = count _pattern; if (_patternSize == 0) exitWith {0}; private _result = 0; // Let _i denote the start of potential match in _array for "_i" from 0 to (count _array - patternSize) do { scopeName "main"; // Let _j denote the number of characters matched so far. private _j = 0; while ((_array select (_i + _j)) isEqualTo (_pattern select j)) do { _j = _j + 1; if (_j == _patternSize) then { //Got a match. Move next search to after current match _i = _i + _j; _result = _result + 1; breakTo "main"; }; }; }; _result }; private _lineBreaks = [toArray _string, toArray "<br/>"] call CountNonOverlappingOccurrences; 1 Share this post Link to post Share on other sites
Lucullus 71 Posted September 30, 2017 Another way: _str = "My first line<br/>My second line<br/>Third line<br/>you guessed it, fifth line<br/>I lied that was the fourth."; _lines = count (_str splitString "/"); hint str (_lines); // 5 1 Share this post Link to post Share on other sites
das attorney 858 Posted September 30, 2017 I would do: _manipulate = "My first line<br/>My second line<br/>Third line<br/>you guessed it, fifth line<br/>I lied that was the fourth."; _manipulate = _manipulate splitString "<>"; _manipulate = _manipulate select {_x find "br/" == -1}; diag_log _manipulate Should return this: ["My first line","My second line","Third line","you guessed it, fifth line","I lied that was the fourth."] Then you can do all the endl stuff with forEach to use it in a tooltip or whatever. 2 Share this post Link to post Share on other sites
code34 248 Posted September 30, 2017 wow nice :) could lead to encapsulte that in parser object Share this post Link to post Share on other sites
Muzzleflash 111 Posted September 30, 2017 The only thing to be careful of with splitString is that it will split on character in the delimiter. So if you split on "<>" you are fine with what @das attorney suggests, since you text will likely not contain those symbols. But if it did, you would be in trouble. 1 Share this post Link to post Share on other sites
7erra 629 Posted September 30, 2017 1 hour ago, Muzzleflash said: The only thing to be careful of with splitString is that it will split on character in the delimiter. That is the reason why I avoided using splitString but @das attorney's method is really simple and fast. Here are the test results: My own solution, worst of all: Spoiler _text = "Line<br/>"; for "_i" from 1 to 100 do { _text = _text +format ["Line %1<br/>",_i]; }; _tCount = count _text; _duration = _tCount/20; _lineHeight = 0.0607143; _br = ["<br/>","<br />"]; _10 = toString [10]; _editString = _text; { _char = count _x; _no = _editString find _x; private _loop = 0; while {-1 != _editString find _x} do { _no = _editString find _x; _splitStr = _editString splitString ""; _splitStr deleteRange [(_no +1), _char -1]; _splitStr set [_no, _10]; _editString = _splitStr joinString ""; }; } forEach _br; _lineCount = {_x == 10} count (toArray _editString); systemChat str _lineCount; _deltaY = _lineCount; [ _text, -1, 0 * safezoneH + safezoneY, _duration, 1, _deltaY, 789 ] spawn BIS_fnc_dynamicText; /* Result: 13.6622 ms Cycles: 74/10000 */ @Muzzleflash's solution: Spoiler _text = "Line<br/>"; for "_i" from 1 to 100 do { _text = _text +format ["Line %1<br/>",_i]; }; // _text will later on be the input text _tCount = count _text; _duration = _tCount/20; _lineHeight = 0.0607143; _br = ["<br/>","<br />"]; _textArray = toArray _text; _lineCount = 0; { _brArray = toArray _x; private _patternSize = count _brArray; if (_patternSize == 0) exitWith {0}; // Let _i denote the start of potential match in _textArray for "_i" from 0 to (count _textArray - _patternSize) do { scopeName "main"; // Let _j denote the number of characters matched so far. private _j = 0; while {(_textArray select (_i + _j)) isEqualTo (_brArray select _j)} do { _j = _j + 1; if (_j == _patternSize) then { //Got a match. Move next search to after current match _i = _i + _j; _lineCount = _lineCount + 1; breakTo "main"; }; }; }; } forEach _br; systemChat str _lineCount; _deltaY = _lineCount; [ _text, -1, 0 * safezoneH + safezoneY, _duration, 1, _deltaY, 789 ] spawn BIS_fnc_dynamicText; /* Result: 5.85965 ms Cycles: 171/10000 */ I edited some script errors and removed the call necessity. And the best of them all: @das attorney's script: _text = "Line<br/>"; for "_i" from 1 to 100 do { _text = _text +format ["Line %1<br/>",_i]; }; _tCount = count _text; _duration = _tCount/20; _lineHeight = 0.0607143; _br = ["<br/>","<br />"]; _manipulate = _text; _manipulate = _manipulate splitString "<>"; _lineCount = {_x find "br/" != -1 OR _x find "br /" != -1} count _manipulate; systemChat str _lineCount; _deltaY = _lineCount; [ _text, -1, 0 * safezoneH + safezoneY, _duration, 1, _deltaY, 789 ] spawn BIS_fnc_dynamicText; /* Result: 0.499251 ms Cycles: 2003/10000 */ The splitString won't be a problem since im only counting "br/" and "br /". Thanks everyone :) 1 Share this post Link to post Share on other sites