Jump to content
M1ke_SK

remove items from array by iteration (not unique values)

Recommended Posts

I am trying to iterate array elements and remove added items. At the end, I am expecting array of NOT added items to unit. When I add item to player, I remove it from array, but in next iteration I skip to next element.

 

Problem: array have 2x "Titan_AT" so array does not have unique keys.

_items = ["Titan_AT","Titan_AT","Titan_AA","NLAW_F","RPG7_F","RPG32_HE_F","RPG32_F"];

{
    systemChat format ["_item: %1 | _items: %2", _x, _items];

    if (player canAdd _x) then 
    {
        player addItem _x;
		
		//remove item from _items;
		//_items = _items - [_x]; //this will delete both "Titan_AT" from array at 1 iteration
		_items deleteAt _forEachIndex; // this will skip next element on new iteration
    };
}
forEach _items;

systemChat format ["not added items: %1", _items];

 

EDIT:

 

I used second array

 

_items = ["Titan_AT","Titan_AT","Titan_AA","NLAW_F","RPG7_F","RPG32_HE_F","RPG32_F"];
_left = [];
{
    if (player canAdd _x) then 
    {
        player addItem _x;
    }
    else 
    {
        _left pushBack _x;
    };

    diag_log format [" _item: %1 | _items: %2 | _left: %3", _x, _items, _left];
}
forEach _items;

systemChat format ["not added items: %1", _left];

 

Share this post


Link to post
Share on other sites

Hey there M1ke_SK, one way I could think you can do it is to set the items you remove to a predetermined value and then run another loop that will delete them (after you have iterated once through the array to add items to your unit).

This could look like this (quoting your code)

private _items = ["Titan_AT", "Titan_AT", "Titan_AA", "NLAW_F", "RPG7_F", "RPG32_HE_F", "RPG32_F"];
{
  systemChat format["_item: %1 | _items: %2", _x, _items];
  if(player canAdd _x) then {
    player addItem _x;
    _items set[_forEachIndex, -1]; // Set the value equal to -1
  };
} forEach _items;

// Loop again through the array to delete the items you removed
private _index = 0; // Initialize an index
while{_index < (count _items)} do {
  // Check if the item at the index position is -1
  if((_items select _index) isEqualTo -1) then {
    _items deleteAt _index; // If it is... delete it and do NOT increment the index
  } else {
    _index = _index + 1; // Otherwise just go to the next position
  };
};

systemChat str _items;

I have only tested this in Single Player and worked OK. I did not test extensively but it worked just fine for all the tests I ran. In general the "trick" here is to NOT increment the index when you delete (because the next element will move down to your current position). So, no matter what way you will choose, one way will be to take care of the index increments.

 

Please let us know if this works for you or if you require something different.

  • Like 1

Share this post


Link to post
Share on other sites

This is how I often do:

 


private _itemsToKeep = [];

 

{

    if (keep_condition) then {

        _itemsToKeep pushBack _x;

    };

} foreach _items;

_items = _itemsToKeep;

 

 

But ZaellixA’s solution also seems like a good one. Except I’d do the delete phase in the first loop and skipped the second.

 

EDIT: Corrected the pseudo style code to more exact SQF code after Dedmen’s comment below. (The ”keep_condition” will still need to be replaced by an actual keep condition.)

Edited by engima
Correction.
  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
20 hours ago, engima said:

This is how I often do

I'm 100% sure you don't. Because that script doesn't work at all.

First the `private` at the top is causing a undefined variable error because that's not how private syntax works.

Second you are only keeping one item, the last item in the array actually.

Third, your array at the end is a single element, and not an array anymore.

 

On 7/28/2019 at 12:50 PM, M1ke_SK said:

I am trying to iterate array elements and remove added items.

Sounds like a usecase for https://community.bistudio.com/wiki/select

 

_items = ["Titan_AT","Titan_AT","Titan_AA","NLAW_F","RPG7_F","RPG32_HE_F","RPG32_F"];

_items = _items select {
    systemChat format ["_item: %1 | _items: %2", _x, _items];

    if (player canAdd _x) then {
        player addItem _x;
        false //Remove element from array
    } else {
        true //Keep element in array
    };
};

systemChat format ["not added items: %1", _items];

 

22 hours ago, ZaellixA said:

// Loop again through the array to delete the items you removed

ughh yuck..

How about

_items = _items - [-1]

Removes every element that's "-1". Sounds simpler than your very complex looking while loop.

 

 

  • Like 3
  • Thanks 1

Share this post


Link to post
Share on other sites

I’d say that ZaellixA’s second while is the one to choose if you for some reason do not want the _items variable to reference a new array. I.e. using the deleteAt command.

  • Like 2
  • Thanks 1

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

×