Jump to content
thy_

[SOLVED] 5 lines only. Can you do it with less?

Recommended Posts

Hello, folks. 

 

Is there any chance you share a faster or more elegant way to write the same result below?

 

Code goal: at the mission starts, search once all named markers and remove all found markers that aren't area markers (rectangles and ellipses), saving the result in a list for further purposes.

Pretty sure even the first code line below could be smarter/complete.  

 

// Search through all markers on the map with the prefix "mark_" and append them in a list:
_areaMarkersOnly = allMapMarkers select {_x find "mark_" isEqualTo 0};  // result example: ["mark_1", "mark_garbage", "mark_2"] but unfortunately including markers with unwanted shapes.

{ // forEach in _areaMarkersOnly:

  // It will be needed to identify what will be deleted later:
  _index = _areaMarkersOnly find _x;
  
  // If the marker (_x) is NOT rectangle and is NOT ellipse, so... 
  if ( (markerShape _x != "RECTANGLE") AND (markerShape _x != "ELLIPSE") ) then
  {
    // delete this marker from my list:
    _areaMarkersOnly deleteAt _index;
  };

} forEach _areaMarkersOnly;

 

SOLVED!

Below, you see the code that works for me after the community advice:

_acceptableShapes = ["RECTANGLE", "ELLIPSE"];
_prefix = "mark_";

if ( !_debug ) then 
	{
		// Selecting only relevant markers:
		_areaMarkersOnly = allMapMarkers select { (_x find _prefix == 0) AND {(markerShape _x) in _acceptableShapes} };
	
	} else {

		// For debugging purporses, the way to select the relevant markers here it is slightly different. Now selecting all markers shapes:
		_areaMarkersOnly = allMapMarkers select { _x find _prefix == 0 };
  
		{ // forEach _areaMarkersOnly:
			// _x index in the list, need it to delete _x from the list:
			_markerIndex = _areaMarkersOnly find _x;
            // if the marker has no the shapes acceptables, do it:
			if ( !((markerShape _x) in _acceptableShapes) ) then
			{
				// delete the marker from the list:
				_possibleMinefields deleteAt _markerIndex;				
				// delete the marker from the map:
				deleteMarker _x;
				// and print this messages:
				systemChat format ["DEBUG > Marker '%1' has NO a rectangle or ellipse shape to be considered a area marker.", _x];
			};
		} forEach _areaMarkersOnly;
	};

 

Edited by thy_
Maybe now the briefing is clearer, Larrow.

Share this post


Link to post
Share on other sites
_markersToReview = allMapMarkers select {_x find "mark_" isEqualTo 0 AND markerShape _x in ["RECTANGLE","ELLIPSE"]};

 

  • Like 3

Share this post


Link to post
Share on other sites

Another one with lazy evaluation:

_markersToReview = allMapMarkers select { ((_x find "mark_") == 0) and { (markerShape _x) in ["ELLIPSE", "RECTANGLE"] } };

 

  • Like 2

Share this post


Link to post
Share on other sites

Notable that when comparing strings, "isEqualTo" is case-sensitive while "==" is not, which may be relevant depending on context.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
7 minutes ago, Harzach said:

"isEqualTo" is case-sensitive while "==" is not

Aware of this, but in our cases isEqualTo is used to compare numbers, and in this context I prefer to use == because it's shorter.

  • Like 2

Share this post


Link to post
Share on other sites
2 hours ago, Schatten said:

Aware of this, but in our cases isEqualTo is used to compare numbers, and in this context I prefer to use == because it's shorter.

 

Yup, just a fun fact, not a comment on anyone's code.

Share this post


Link to post
Share on other sites

By the way, find is case-sensitive, so if you need case-insensitive, you can use, for example, toLowerANSI:

((toLowerANSI _x) find "mark_") == 0

 

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
9 hours ago, thy_ said:

Code goal: search all named markers on Eden Editor and remove all found markers that aren't area markers (rectangles and ellipses).

 

 

9 hours ago, thy_ said:

remove all found markers that aren't area markers

Erm, you all missed the specs.😀

 

9 hours ago, thy_ said:

search all named markers on Eden Editor

Ambiguous, on == ? in/from ?

 

All named markers from Eden Editor ( ie in a mission )...

{ deleteMarker _x } forEach ( allMapMarkers select { _x find "mark_" == 0 && { !( markerShape _x in [ "ELLIPSE", "RECTANGLE" ] ) } } );

 

All named markers in Eden Editor ( ie in the editor  )...

delete3DENEntities ( all3DENEntities #5 select{ (_x get3DENAttribute "markerName") #0 find "mark_" == 0 && { !(( _x get3DENAttribute "markerType" ) #0 in [0,1] ) } } )

 

  • Like 3

Share this post


Link to post
Share on other sites
3 minutes ago, Larrow said:

All named markers from Eden Editor ( ie in a mission )...


{ deleteMarker _x } forEach ( allMapMarkers select { _x find "mark_" == 0 && { !( markerShape _x in [ "ELLIPSE", "RECTANGLE" ] ) } } );

 

 

 

😅 but how could I save the search in the _markersToReview array in this specific case?  

 

Share this post


Link to post
Share on other sites
10 hours ago, thy_ said:

Code goal: search all named markers in a mission and remove all found markers that aren't area markers (rectangles and ellipses).

13 minutes ago, thy_ said:

but how could I save the search in the _markersToReview array in this specific case?

 

  1.  Not mentioned in Code Goal
  2. As per your initial code there would be nothing to review as the variable is local and would be destroyed at the scope end.
  3. If you remove the markers, what's left over to review? So you don't actually want to remove(delete) markers just make a list of all "mark_" markers that are not area markers. 

Code Goal: Make a list of all markers named in the editor starting with "mark_" that are not area markers.

copyToClipboard format[ "Non area 'mark_' markers: %1", allMapMarkers select { _x find "mark_" == 0 && { !( markerShape _x in [ "ELLIPSE", "RECTANGLE" ] ) } } ];

 

 

  • Like 2

Share this post


Link to post
Share on other sites
// Lots of code...

_acceptableShapes = ["RECTANGLE", "ELLIPSE"];
_prefix = "mark_";

if ( !_debug ) then 
	{
		// Selecting only relevant markers:
		_areaMarkersOnly = allMapMarkers select { (_x find _prefix == 0) AND {(markerShape _x) in _acceptableShapes} };
	
	} else {

		// For debugging purporses, the way to select the relevant markers here it is slightly different. Now selecting all markers shapes:
		_areaMarkersOnly = allMapMarkers select { _x find _prefix == 0 };
  
		{ // forEach _areaMarkersOnly:
			// _x index in the list, need it to delete _x from the list:
			_markerIndex = _areaMarkersOnly find _x;
            // if the marker has no the shapes acceptables, do it:
			if ( !((markerShape _x) in _acceptableShapes) ) then
			{
				// delete the marker from the list:
				_possibleMinefields deleteAt _markerIndex;				
				// delete the marker from the map:
				deleteMarker _x;
				// and print this messages:
				systemChat format ["DEBUG > Marker '%1' has NO a rectangle or ellipse shape to be considered a area marker.", _x];
			};
		} forEach _areaMarkersOnly;
	};

// Lots of code...

 

Share this post


Link to post
Share on other sites

Little question 🙄  Why are you placing markers, then delete them at start, but after saving... what ? strings of future ex-markers?

What is the final goal? Don't forget markers can be local and be hidden or displayed by alpha color param.

  • Like 2

Share this post


Link to post
Share on other sites
20 minutes ago, pierremgi said:

Little question 🙄  Why are you placing markers, then delete them at start, but after saving... what ? strings of future ex-markers?

What is the final goal? Don't forget markers can be local and be hidden or displayed by alpha color param.


😅

It will be a script where you drag and drop area-markers on Eden Editor, re-name them and that's it. Through a parameter file, you manage everything about your minefields. 

WIP, just one of some functions:

THY_fnc_DAMM_minefields_scanner = {
	// This function search and append in a list all area-markers confirmed as a real minefield. The searching take place once right at the mission begins.
	// Returns _confirmedMinefields.

	params ["_prefix", "_spacer"];
	private ["_realPrefix", "_acceptableShapes", "_txtDebugHeader", "_txtWarningHeader", "_txtWarning_1", "_confirmedMinefields", "_possibleMinefields", "_index", "_mfNameStructure", "_spacerAmount", "_itShouldBeNumber"];

	_realPrefix = _prefix + _spacer;
	_acceptableShapes = ["RECTANGLE", "ELLIPSE"];
	
	// Debug txts:
	_txtDebugHeader = "DAMM SCRIPT DEBUG >";
	_txtWarningHeader = "DAMM SCRIPT WARNING >";
	_txtWarning_1 = format ["If the intension is make it as minefield, its sctructure name must be '%1number'. Otherwise, just ignore this message.", _realPrefix];

	// Initial values:
	_confirmedMinefields = [];

	// Step 1/2 > Creating a list with only area markers with right prefix:
	if ( !DAMM_debug ) then {
		// Smarter and faster solution, searching and creating the list:
		_possibleMinefields = allMapMarkers select { (_x find _realPrefix == 0) AND {(markerShape _x) in _acceptableShapes} };
	
	} else {

		// As the slower solution, for debugging purporses, the way to select the relevant markers here it is slightly different. Now searching for all marker shapes:
		_possibleMinefields = allMapMarkers select { _x find _realPrefix == 0 };
		{ // forEach _possibleMinefields:
			// It will be needed to identify what will be deleted later:
			_index = _possibleMinefields find _x;
			// if the marker has no the shapes acceptables, do it:
			if ( !((markerShape _x) in _acceptableShapes) ) then {
				// delete the marker from the list:
				_possibleMinefields deleteAt _index;
				// delete the marker from the map:
				//deleteMarker _x;
				// and print this messages:
				systemChat format ["%1 Marker '%2' has NO a rectangle or ellipse shape to be considered a minefield.", _txtDebugHeader, _x];
			};
		} forEach _possibleMinefields;
	};

	// Step 2/2 > Deleting to the list those selected markers that don't fit the name's structure rules:
	{  // forEach _possibleMinefields:
		// check if the marker name has more than one _spacer character in its string composition:
		_mfNameStructure = _x splitString "";
		_spacerAmount = count (_mfNameStructure select { _x find _spacer isEqualTo 0});
		// if the _spacer is been used correctly:
		if ( _spacerAmount == 1 ) then {
			// spliting the marker name to check its structure:
			_mfNameStructure = _x splitString _spacer;
			// picking up the second/last string and convert it to integer:
			_itShouldBeNumber = parseNumber (_mfNameStructure select 1);  // result will be a number extracted from string OR ZERO if inside the string has no numbers.
			// if the second/last string is numeric, and the marker structure's name is composed by 2 strings, do it:
			if ( _itShouldBeNumber != 0 AND ((count _mfNameStructure) == 2) ) then {
				// the area marker represents a confirmed minefield:
				_confirmedMinefields append [_x];
				//if ( DAMM_debug ) then { systemChat format ["%1 The marker '%2' is a confirmed minefield.", _txtDebugHeader, _x] };

			} else {
				// Warning message:
				systemChat format ["%1 Marker called '%2' has NO a valid name. %3", _txtWarningHeader, _x, _txtWarning_1];
			};
			
		} else {
			// Warning message:
			systemChat format ["%1 Marker called '%2' has more than 1 prefix spacer (%3). %4", _txtWarningHeader, _x, _spacer, _txtWarning_1];
		};
	} forEach _possibleMinefields;

	// Debug message:
	if ( DAMM_debug ) then { systemChat format ["%1 Minefields built: %2", _txtDebugHeader, _confirmedMinefields] };
	// Returning:
	_confirmedMinefields;
};

 

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×