Notifications
Clear all

[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.

13 Replies
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
-----------------------------------------

collect is faster for sure.

1 Reply
(@polytools3d)
Joined: 11 months ago

Posts: 0

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)
2 Replies
(@gtafan)
Joined: 11 months ago

Posts: 0

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?

(@serejah)
Joined: 11 months ago

Posts: 0

Correct.
As of node marking I guess it depends on whether you need to store this data within scene or node.

Page 1 / 2