SOliver Posted March 31, 2011 Posted March 31, 2011 (edited) Alright folks, A few months ago I wrote a data collection program for one of the councils which basically read scraped all the blocks in x amount of drawings and store the information in a MS access database. This got me thinking is it worth removing an item from an array after it is matched to a an item from a list using simple iteration. For example ;For the sake of the discussion topic imagine vl-sort doesn't exist (setq BlockList(list [List of block objects from the block table])) (setq modelSpaceBlocks (list [<x> All blocks within modelspace])) (vlax-for BlockListc (setq i -1) (while (< (setq i(1= i))(length modelSpaceBlocks)) (if(equals (vla-getName c)(vla-getName (nth i modelSpaceBlocks)) (progn ;Do something with the block ;-------------------- Include or leave out? -------------- (vl-remove (nth i modelSpaceBlocks) modelSpaceBlocks) ;---------------------------------------------------------- ) ) ) ) Perhaps not the best example but surely there must be a point where the value of x is high enough that iterating through it each time. It may be the case that the first 500 blocks remove slow the program down but gradually as the list is reduced in size the process wouldn't be comparing against redundant blocks. Any one have any thoughts on the subject or better yet has anyone ran a comparison? SOliver. Edited March 31, 2011 by SOliver erroneous line of code Quote
alanjt Posted March 31, 2011 Posted March 31, 2011 I'd be more concerned about you stepping through the same modelSpaceBlocks list each type you get to a new item in BlockListc. When you step through BlockListc, just check if it's name is a member (or vl-position) of a pre-stepped through modelSpaceBlocks list that's comprised of nothing but names (mapcar 'vla-get-name modelSpaceBlock). Quote
SOliver Posted March 31, 2011 Author Posted March 31, 2011 I'd be more concerned about you stepping through the same modelSpaceBlocks list each type you get to a new item in BlockListc.When you step through BlockListc, just check if it's name is a member (or vl-position) of a pre-stepped through modelSpaceBlocks list that's comprised of nothing but names (mapcar 'vla-get-name modelSpaceBlock). Removed the i equal list length - wasn't meant to be there. Mapcar would certainly be a more suitable setup that what is there, I spend far too much time with php lol. Don't suppose you could provide an example of how you would implement vl-position? Quote
alanjt Posted March 31, 2011 Posted March 31, 2011 Snippet based on your above provided code (in this situation, member is the same, vl-position just happens to be a tiny bit faster). (setq modelSpaceBlocks (mapcar 'vla-getName modelSpaceBlocks)) ;; STUFF (if (vl-position (vla-getName c) modelSpaceBlocks) ;; DO STUFF ) Quote
BlackBox Posted March 31, 2011 Posted March 31, 2011 AutoLISP Reference Guide > AutoLISP Functions > V Functions > vl-position Returns the index of the specified list item (vl-position [i]symbol list[/i]) Arguments symbol Any AutoLISP symbol. list A true list. Return Values An integer containing the index position of symbol in list; otherwise nil if symbol does not exist in the list. Note that the first list element is index 0, the second element is index 1, and so on. Examples _$ [i](setq stuff (list "a""b" "c" "d" "e"))[/i] ("a" "b" "c" "d" "e") _$ [i](vl-position "c" stuff)[/i] 2 Meaningless text so I can make this post. Quote
BlackBox Posted March 31, 2011 Posted March 31, 2011 Snippet based on your above provided code ... Just curious; perhaps I'm missing something.... I'd think it a duplication of work to step through a block collection, saving the Vla-Objects to a list (modelSpaceBlocks), only to use (mapcar 'vla-get-name modelSpaceBlocks) to get a list of block names... instead, would this not be simpler: (if (setq ss (ssget "_x" (list '(0 . "INSERT") (cons 410 (getvar 'ctab))))) (progn (vlax-for x (setq ss (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))) (if (not (vl-position (setq n (vla-get-name x)) blockList)) (setq blockList (cons (vla-get-name x) blockList)))) (if (vl-position "[color=red]blockName[/color]" blockList) [color=seagreen];; do something [/color] ) (vla-delete ss))) Quote
SOliver Posted March 31, 2011 Author Posted March 31, 2011 (edited) Ah I see what you're gettin' at I think: Run through the list once to gather the names and then use vl-position as a replace meant for the double vla-get-name? I suppose what might be a good idea is to create a list of lists for each block name and store the indices in each list for example: # (setq BlockIndices (list ("sampleBlockName" 1 25 40) ("otherBlock" 3 5 7) )) And use vla-item to pick items as the BlockList iterates Above would mean the modelSpaceBlocks list will have an equal number (or less) items as the blockList. Which would be follwed with something like: (vlax-for c BlockList (setq i -1) (while (< )setq i(1+ i))(length blockIndices)) (if(equal (vla-get-name c)(nth i (car blockIndices)) (progn (someFunction(mapcar '(lambda(y)(nth x modelSpaceBlocks )) (cadr modelSpaceBlocks) ) (setq i (length blockIndices)) ) ) ) There would only be one comparison of the names and then mapcer to pick them up Edited March 31, 2011 by SOliver Extension, erroneous line of code Quote
alanjt Posted March 31, 2011 Posted March 31, 2011 Just curious; perhaps I'm missing something.... I'd think it a duplication of work to step through a block collection, saving the Vla-Objects to a list (modelSpaceBlocks), only to use (mapcar 'vla-get-name modelSpaceBlocks) to get a list of block names... instead, would this not be simpler: (if (setq ss (ssget "_x" (list '(0 . "INSERT") (cons 410 (getvar 'ctab))))) (progn (vlax-for x (setq ss (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object)))) (if (not (vl-position (setq n (vla-get-name x)) blockList)) (setq blockList (cons (vla-get-name x) blockList)))) (if (vl-position "[color=red]blockName[/color]" blockList) [color=seagreen];; do something [/color] ) (vla-delete ss))) More than likely, but I based on the information provided, that was the best I could come up with. Not sure why he would have other lists. Quote
BlackBox Posted March 31, 2011 Posted March 31, 2011 More than likely, but I based on the information provided, that was the best I could come up with. Not sure why he would have other lists. No worries, you were explicit about providing an example based on the OP's code. Ah I see what you're gettin' at I think: Run through the list once to gather the names and then use vl-position as a replace meant for the double vla-get-name? I suppose what might be a good idea is to create a list of lists for each block name and store the indices in each list for example: # (setq BlockIndices (list ("sampleBlockName" 1 25 40) ("otherBlock" 3 5 7) )) And use vla-item to pick items as the BlockList iterates Above would mean the modelSpaceBlocks list will have an equal number (or less) items as the blockList. Which would be follwed with something like: (vlax-for [color=red][b]blockList[/b][/color] [b][color=blue]c[/color][/b] (setq i -1) (while (< )setq i(1+ i))(length blockIndices)) (if(equal (vla-get-name c)(nth i (car blockIndices)) (progn (someFunction(mapcar '(lambda(y)(nth x modelSpaceBlocks )) (cadr modelSpaceBlocks) ) (setq i (length blockIndices)) ) ) ) There would only be one comparison of the names and then mapcer to pick them up This just confuses me to no end ... Also, watch your syntax: ([b]foreach[/b] [b][color=#0000ff]symbol[/color][/b] [color=red][b]List[/b][/color] ([b]vlax-for [color=blue]symbol[/color][/b] [color=red][b]collection[/b][/color] Quote
SOliver Posted March 31, 2011 Author Posted March 31, 2011 No worries, you were explicit about providing an example based on the OP's code. This just confuses me to no end ... Also, watch your syntax: ([b]foreach[/b] [b][color=#0000ff]symbol[/color][/b] [color=red][b]List[/b][/color] ([b]vlax-for [color=blue]symbol[/color][/b] [color=red][b]collection[/b][/color] Lol thanks; I'm writing the code in the quick post didn't even notice I had it back to front:lol: The code you've quoted covers all the comparisons in one iteration through modelSpaceBlocks and then uses the indices to in the subsequent mapcar to collect all the blocks associated with the current blockList item's name. The method that would need to be used to create blockIndices would be a bit messy or at least not suited to mapcar if using sset to get the blocks. This would however have the fewest vlax*,vla*, vl* calls - I think EDUT: In hindsight this post may not explain the blockIndices list creation very well. I'm working at the moment but will try to post a suitable method when I finish. Quote
SOliver Posted March 31, 2011 Author Posted March 31, 2011 Well after pondering on how to write the function to create the function it dawned on me that we've deviated from the topic in such a way that my approach to indexing would benefit from vl-sort for quickness of collecting blocks (sort by object type and name) which would then make the second part redundant as you'd be as well just using the vl-sort and creating the a list containing a list containing a list of block references grouped by name with only one iteration through the blocks. Perhaps the opening example wasn't the best for the discussion - if nothing else I've learned a lot Quote
Lee Mac Posted April 1, 2011 Posted April 1, 2011 (edited) I'm a bit late to the party, but, after glancing through the posts in this thread it appears things are being overcomplicated. Here's the way I see things: If you need to operate on the block definitions for all blocks in Modelspace, then Renderman's code from here is the route I would be inclined to follow, since you only need to process one Block Reference for each Block Definition. If you are performing an operation to affect each Block Reference (for example changing the properties per Reference, or accessing the attributes for an attributed block), then a list needn't be created and you would just iterate through all block references in an acquired SelectionSet. Looking over your code, SOliver, I notice you using indexes to iterate through lists. Whilst in languages such as C/C++ where arrays are used within for loops, this is the usual practice: #include <iostream> using namespace std; int main ( ) { int myArray[5] = {1,2,3,4,5}; int total = 0; for(int i=0; i<5; i++) total += myArray[i]; cout << "Total is: " << total << endl; return 0; } (Excuse my simple example) LISP makes things easy by supplying the developer with tools such as foreach/vlax-for loops, hence removing the need to create and iterate using an index. Same example in LISP: (defun test ( / myArray total ) (setq myArray '(1 2 3 4 5)) (setq total 0) (foreach x myArray (setq total (+ total x)) ) (princ (strcat "\nTotal: " (itoa total))) (princ) ) Hope this offers something helpful. Lee Edited April 1, 2011 by Lee Mac Quote
alanjt Posted April 1, 2011 Posted April 1, 2011 I'm a bit late to the party, but, after glancing through the posts in this thread it appears things are being overcomplicated. Spoken by the man posting C in a LISP forum. Quote
Lee Mac Posted April 1, 2011 Posted April 1, 2011 Spoken by the man posting C in a LISP forum. C++ :wink: Quote
BlackBox Posted April 1, 2011 Posted April 1, 2011 ... If you need to operate on the block definitions for all blocks in Modelspace, then Renderman's code from here is the route I would be inclined to follow, since you only need to processed one Block Reference for each Block Definition. ... Thanks, Lee! Quote
Lee Mac Posted April 1, 2011 Posted April 1, 2011 What. ever. It was posted to demonstrate a point - what's the problem? Quote
SOliver Posted April 3, 2011 Author Posted April 3, 2011 It was posted to demonstrate a point - what's the problem? (quote chosen solely due to it's position in the sub topic) Not one to be pedantic but the code posted would be c && c++ Compatible I've never been a fan of the "foreach" function, again probaly down to too much php [sic] I wrote several function in lisp to mimic php's array handling. Lisp doesn't have a "return" function which is one of the reason why I use iterators as a method of cutting an action short if required. That said vlax-for has a small place in my heart for odbx-based scripts. To be honest the thread went on a tangent from the offset and the comments made by RenderMan and Alanjt sent me off on a wild lisp fuelled by curiosity and an obsession for efficiency The thread was originally opened to discuss the point in which vl-remove becomes useful - granted to my discredit the example was at best misleading. Final note: This thread gave me a slight sense of shame. The production code mentioned in the first post, while not completely conforming to the example; could have been drastically improved if I had started this thread earlier. Still he who makes mistakes and notes them staggers closer to enlightenment. SOliver. Quote
Lee Mac Posted April 3, 2011 Posted April 3, 2011 Not one to be pedantic but the code posted would be c && c++ Compatible I didn't think the include statements would be compatible, nor that C had a 'cout' expression, only printf? Quote
SOliver Posted April 3, 2011 Author Posted April 3, 2011 I didn't think the include statements would be compatible, nor that C had a 'cout' expression, only printf? Lol you've got me there Lee; the post was ill-informed trolling. I haven't touched either languages in years. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.