[Closed] remoove nodes matching some defined condition from an array
I have an array of nodes and would like to remoove all nodes that have, for example some userProp set.
for i=array.count to 1 by -1 where checkUserProp array[i] do deleteItem array i
checkUserProp is your function that checks particular property and return true/false
upd. slow and unusable.
An alternative, especially for very big arrays, could be:
arr = for node in arr where not CheckUserProp node collect node
this is the universal solution for filtering something in some list:
fn filterCollection items filter args: =
(
for item in items where filter item args:args collect item
)
fn filterByName node args: = (matchpattern node.name pattern:args[1] ignoreCase:args[2])
fn filterByClass node args: = (iskindof node args)
fn filterByColor node args: = (node.wirecolor == args)
-- for example: -------------------
with redraw off
(
delete objects
for k=1 to 40 do #(point, box, dummy, circle)[random 1 4] position:(random -[100,100,100] [100,100,100]) wirecolor:(#(red, green, yellow)[random 1 3])
)
one_in_name = filterCollection helpers filterByName args:#("*1*", true)
select one_in_name
dummy_nodes = filterCollection selection filterByClass args:helper
green_nodes = filterCollection geometry filterByColor args:green
another more ‘fancy’ example:
fn filterNumbers number args: = (args number)
values = for k=1 to 100 collect (random 1 100000)
odd_numbers = filterCollection values filterNumbers args:(fn oddNumber item = (mod item 2 == 1))
I did a little test with mine and Jorge’s code and now it is clear that deleteItem was a bad idea.
It is almost four times slower then collect on 100k array. I guess each time deleteItem is used it forces max to reinitialize array
Some tests for comparison (deleteItem() vs collect()):
(
local arr = #()
local total = 0
fn BuildTestArray =
(
seed 0; free arr; gc light:on
arr = for j = 1 to total collect random black white
)
fn RunTests limit =
(
BuildTestArray()
st=timestamp(); sh=heapfree
for j = arr.count to 1 by -1 where arr[j].value > limit do deleteitem arr j
time = formattedprint (timestamp()-st) format:"4d"
format "time:%ms heap:% removed:%
" time (sh-heapfree) (total-arr.count)
BuildTestArray()
st=timestamp(); sh=heapfree
arr = for j in arr where not j.value > limit collect j
time = formattedprint (timestamp()-st) format:"4d"
format "time:%ms heap:% removed:%
" time (sh-heapfree) (total-arr.count)
format "-----------------------------------------
"
windows.processpostedmessages()
)
for j = 1 to 5 do
(
total = j * 100000
format ("TEST " + (j as string) + " of 5 - " + (total as string) + " Items
")
RunTests 50
RunTests 100
RunTests 200
format "
"
)
)
/* TEST 1 of 5 - 100000 Items */
time: 34ms heap:204L removed:99285
time: 22ms heap:280L removed:99285
-----------------------------------------
time: 62ms heap:204L removed:93933
time: 22ms heap:280L removed:93933
-----------------------------------------
time: 201ms heap:204L removed:51653
time: 23ms heap:280L removed:51653
-----------------------------------------
/* TEST 2 of 5 - 200000 Items */
time: 76ms heap:204L removed:198529
time: 44ms heap:280L removed:198529
-----------------------------------------
time: 193ms heap:204L removed:187863
time: 44ms heap:280L removed:187863
-----------------------------------------
time: 853ms heap:204L removed:103501
time: 47ms heap:280L removed:103501
-----------------------------------------
/* TEST 3 of 5 - 300000 Items */
time: 123ms heap:204L removed:297802
time: 66ms heap:280L removed:297802
-----------------------------------------
time: 386ms heap:204L removed:281893
time: 65ms heap:280L removed:281893
-----------------------------------------
time:1924ms heap:204L removed:155392
time: 70ms heap:280L removed:155392
-----------------------------------------
/* TEST 4 of 5 - 400000 Items */
time: 180ms heap:204L removed:397011
time: 88ms heap:280L removed:397011
-----------------------------------------
time: 646ms heap:204L removed:375857
time: 88ms heap:280L removed:375857
-----------------------------------------
time:3401ms heap:204L removed:207134
time: 93ms heap:280L removed:207134
-----------------------------------------
/* TEST 5 of 5 - 500000 Items */
time: 248ms heap:204L removed:496238
time: 110ms heap:280L removed:496238
-----------------------------------------
time: 983ms heap:204L removed:469781
time: 110ms heap:280L removed:469781
-----------------------------------------
time:5309ms heap:204L removed:258528
time: 115ms heap:280L removed:258528
-----------------------------------------
Yes it is. In the test collect() basically goes from 2 to 45 times faster than deleting items from the array.
If there are no items matching the search criteria, meaning no items are removed, then the times are almost the same.
Thanks for help. However now after taking a look at that collect thing I think that I posibly doing it wrong. So here an explanation of what I want to do:
I want to export a model that can have many nodes, but some of them like lights, partikle, collision meshes, etc. should not be exported. After selecting all the nodes in the scene the folowing code should run:
arr=selection as array –alll selected nodes as array
remooveUnused arr – function that remooves all nodes that should not be exported
export arr – export function
The maxscript code is posibly not 100% corect just wrote it from memory.
You don’t actually need to remove anything from the initial array.
Create new array containing nodes that are valid to export and pass it to your export function
All you need is to implement filter function that checks if node is ok to export based on some criteria.
export (for n in selection where validForExport n collect n)
By filter function that checks if node is ok, you mean validForExport, right?
Also what would be the best way to mark nodes, that shouldn´t be exported? Is userproperty a good idea?
Correct.
As of node marking I guess it depends on whether you need to store this data within scene or node.