Author Topic: Convert a List to a String ...  (Read 6720 times)

0 Members and 1 Guest are viewing this topic.

Hangman

  • Swamp Rat
  • Posts: 566
Convert a List to a String ...
« on: May 26, 2010, 12:17:53 PM »
Okay, I give up.  I've been searching the database and the help file for a way to pull the items of a list and put them into a string for display.
My initial thought was to use 'Length' to get the number of layers listed, then create a bunch of variables to put each layer in:
Code: [Select]
(setq LayrLength (length GV_LayersOff))
  (setq L-a (nth 0 GV_LayersOff)
          L-b (nth 1 ...
-but realized this isn't going to work.  I guess if I could figure out how to make a variable for each item in the list, but this would be horrendous just to display the layers that are currently off.

I have an ALERT that I want to display to the users:
Code: [Select]
(ALERT (strcat "The following Layers are currently Off: \n" GV_LayersOff))
-where GV_LayersOff is a list of current layers off; from here:
Code: [Select]
...
(setq LayrInfo (tblnext "Layer" 'T))                       ; set variable to first layer (zero)
 (while LayrInfo
  (setq LayrName (cdr (assoc 2 LayrInfo))                   ; get layer name
        LayrColr (cdr (assoc 62 LayrInfo))                  ; get layer color
        LayrInfo (tblnext "Layer")                          ; set variable to next layer
  )
  (if (minusp LayrColr)                                     ; if layer color is negative,
   (setq GV_LayersOff (cons LayrName GV_LayersOff))         ; the layer is off, add to list.
  )
 ); while
 ...

I would prefer to display to the users something like this:
Quote
The following Layers are currently Off:
     Layer_1
     Layer_2
     Layer_3
     Layer_4

But at the moment, I'd be happy just to get the List into a string.

I have found many comments regarding how easy it is, but no code to use as an example.  I've searched the help file but haven't stumbled upon anything yet.   What's frustrating is something I thought would be easy has turned into two hours of research and still have not gotten anywhere.

Will you help me please?.  Thanks.
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Lee Mac

  • Seagull
  • Posts: 12923
  • London, England
Re: Convert a List to a String ...
« Reply #1 on: May 26, 2010, 12:27:33 PM »
Here are two for you to play around with  :-)

Code: [Select]
(defun lst->str ( lst del )
  (if (cdr lst)
    (strcat (car lst) del (lst->str (cdr lst) del))
    (car lst)
  )
)

Code: [Select]
(defun lst->str ( lst del )
  (
    (lambda ( str )
      (foreach x (cdr lst)
        (setq str (strcat str del x))
      )
      str
    )
    (car lst)
  )
)

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: Convert a List to a String ...
« Reply #2 on: May 26, 2010, 12:57:25 PM »
The entire thread is educational, but it goes from string->list to list->string at this point.
http://www.theswamp.org/index.php?topic=32845.msg383391#msg383391

Nice submissions Lee. :)
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

Lee Mac

  • Seagull
  • Posts: 12923
  • London, England
Re: Convert a List to a String ...
« Reply #3 on: May 26, 2010, 01:09:19 PM »
Thanks Alan, I agree - that is a great thread for someone who's learning  ;-)

Hangman

  • Swamp Rat
  • Posts: 566
Re: Convert a List to a String ...
« Reply #4 on: May 26, 2010, 01:14:36 PM »
The entire thread is educational, but it goes from string->list to list->string at this point.
http://www.theswamp.org/index.php?topic=32845.msg383391#msg383391
 ...

Yes Alan, it is.  That was one of those I read over and over again for the last hour trying to comprehend it.
I need to put out a thought request for you guys here, and I know it'll drive you nuts, but it really helps us in learning how and why you are using certain functions in certain places.  If you would please put comments after each line of code, it would really help.   ^-^

Thank you Lee, I will disect these and see what I can understand.  I still have trouble with 'Lambda', I'm not yet comprehending the implications of such a powerful tool nor its position in the code.
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Lee Mac

  • Seagull
  • Posts: 12923
  • London, England
Re: Convert a List to a String ...
« Reply #5 on: May 26, 2010, 01:34:16 PM »
As a quick explanation, lambda is an anonymous function, in this case taking one argument. It is used in places where defining a whole subfunction for a simple task seems a bit redundant. The lambda function makes things convenient, in this case, I don't have to define the variable 'str' before entering the foreach loop - I can just feed it the value through the lambda function.

As another quick example of it being used in this way:

Code: [Select]
(if (setq ss (ssget))
  (
    (lambda ( i / lst )
      (while (setq ent (ssname ss (setq i (1+ i))))
        (setq lst (cons ent lst))
      )
      lst
    )
    -1
  )
)

Notice here also, it is a convenience, as we don't need to have (setq i -1) before the while loop.

As for the comments - I'm probably the world's worst for commenting - I don't think I use any at all. I know this is probably considered bad practice, but to be perfectly honest, when reading code, I find comments distracting and sometimes even misleading - I prefer to interpret the code myself.

« Last Edit: May 26, 2010, 01:48:32 PM by Lee Mac »

jmcshane

  • Newt
  • Posts: 83
Re: Convert a List to a String ...
« Reply #6 on: May 26, 2010, 02:04:07 PM »
Hi Hangman,

I know this is really answering your question, but if you have maybe 200+ layers in your drawing that are turned off,
it's going to be an awful big alert box!!

But I hear what you are saying about list to string. I am having difficulty with it myself.

Thanks for the link and the example Alan and Lee.
A nice little bit of homework.

For what its worth, here is what I use to print to the textscreen, and if you want you could use the following line for the alert
Code: [Select]
(alert "\nPress F2 to see list of layers that are OFF")
Code: [Select]
(defun c:LayerListoff  (/ LayerTable LayerOffList)
  (vl-load-com)
  (setq LayerTable (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))))
  (vlax-for LayerName  LayerTable
    (if (= (vla-get-layeron LayerName) :vlax-false)
      (progn (setq LayerOffList (acad_strlsort (cons (vla-get-name LayerName) LayerOffList)))
             (princ (strcat "\n" (vla-get-name LayerName) " is turned OFF."))
        )
      )
    )
  (princ (strcat "\n" (itoa (length LayerOffList)) " Layers are turned OFF."))
  (setq LayerOffList nil)
  (princ)
  )

John.

Civil 3D 2021. Windows 10

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: Convert a List to a String ...
« Reply #7 on: May 26, 2010, 02:12:32 PM »
You could always vl-princ-to-string the list, then alert it. LoL
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

jmcshane

  • Newt
  • Posts: 83
Re: Convert a List to a String ...
« Reply #8 on: May 26, 2010, 02:17:59 PM »
Quote
You could always vl-princ-to-string the list, then alert it. LoL
Classic! :-D
John.

Civil 3D 2021. Windows 10

Lee Mac

  • Seagull
  • Posts: 12923
  • London, England
Re: Convert a List to a String ...
« Reply #9 on: May 26, 2010, 02:18:56 PM »
But I hear what you are saying about list to string. I am having difficulty with it myself.

If it helps at all, I would think about it like this: You need a string to start with, whether it be an empty string ( "" ) or something else, you need a string, as you are, with every item in the list, setting the output to itself + the new item.

Code: [Select]
(foreach x '("1" "2" "3" "4" "5")

  (setq str (strcat str x))

)

If 'str' were nil before the loop, we would have an error, as
Code: [Select]
(strcat nil "1") is not valid.

So say, we set 'str' to an empty string:

Code: [Select]
(setq str "")

(foreach x '("1" "2" "3" "4" "5")

  (setq str (strcat str x))

)

Now, with every item, the value of str will be:

Code: [Select]
x = "1", str = "1"
x = "2", str = "12"
x = "3", str = "123"
etc

We can use this method with a delimiter if need be:

Code: [Select]
(setq str "")

(foreach x '("1" "2" "3" "4" "5")

  (setq str (strcat str x ","))

)

Notice that in this way we receive:

Code: [Select]
str = "1,2,3,4,5,"

And we have a trailing delimiter on the end - so we can get around this by setting the value of 'str' to the first element in the list instead of the empty string, and iterating through the rest of the list with the delimiter between the existing 'str' and new value:

Code: [Select]
(setq str "1")

(foreach x '("2" "3" "4" "5")

  (setq str (strcat str "," x))

)

Code: [Select]
x = "2", str = "1,2"
x = "3", str = "1,2,3"
etc

Of course, this is a specific example - so we can replace "," with a variable denoting the delimiter, and use list operations on the list of items:

Code: [Select]
(setq lst '("1" "2" "3" "4" "5"))

(setq str (car lst) del ",")

(foreach x (cdr lst)

  (setq str (strcat str del x))

)

I hope this clarifies things a bit better,

Lee

Hangman

  • Swamp Rat
  • Posts: 566
Re: Convert a List to a String ...
« Reply #10 on: May 26, 2010, 02:27:03 PM »
Hi Hangman,

I know this is really answering your question, but if you have maybe 200+ layers in your drawing that are turned off,
it's going to be an awful big alert box!!
 ...
For what its worth, here is what I use to print to the textscreen, and if you want you could use the following line for the alert
Code: [Select]
(alert "\nPress F2 to see list of layers that are OFF") ...

Oh, good advice John, I didn't even think of that.  I hope we don't have 200+ layers off, but you never know.


Quote from: Lee Mac
...
As for the comments - I'm probably the world's worst for commenting - I don't think I use any at all. I know this is probably considered bad practice, but to be perfectly honest, when reading code, I find comments distracting and sometimes even misleading - I prefer to interpret the code myself.

I understand Lee.  I try to put in the comments, but I find myself interpreting the code rather than just reading my own comments.  I think it is good practice to interpret the code, keeps the mind busy, but as I mentioned, for those of us not familiar with where the line of code is going, it's difficult to interpret.  Especially when you have a piece of code like 'lambda'.  When we go to the help file for the definition, its somewhat eluding because there are so many applications.  It makes it difficult to fully understand the use of it.
Anyway, enough on that one.  I thank you for the explanation.
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

alanjt

  • Needs a day job
  • Posts: 5352
  • Standby for witty remark...
Re: Convert a List to a String ...
« Reply #11 on: May 26, 2010, 02:28:34 PM »
Lee already posted a great explanation, but I wrote this and got sidetracked, so I'm posting it anyway...

Code: [Select]
(defun foo (lst del / str)
  (setq str (car lst)) ; set string based on first item of list
  (foreach x (cdr lst) ; step through list (except first item, since we alreaded appended it to your string
    (setq str (strcat str del x)) ; append 'next' item in list to string (separated with deliminator)
  )
)
Civil 3D 2019 ~ Windohz 7 64bit
Dropbox

jmcshane

  • Newt
  • Posts: 83
Re: Convert a List to a String ...
« Reply #12 on: May 26, 2010, 02:29:57 PM »
Quote
I hope this clarifies things a bit better

Cheers Lee,
That sheds some light on the subject.
I'll have to look at it in more detail tomorrow as I have to get out of this place!! :-D

John.

Civil 3D 2021. Windows 10

Hangman

  • Swamp Rat
  • Posts: 566
Re: Convert a List to a String ...
« Reply #13 on: May 26, 2010, 02:44:43 PM »
...
If it helps at all, I would think about it like this: You need a string to start with, whether it be an empty string ( "" ) or something else, you need a string, as you are, with every item in the list, setting the output to itself + the new item.

Code: [Select]
(foreach x '("1" "2" "3" "4" "5")

  (setq str (strcat str x))

)

If 'str' were nil before the loop, we would have an error, as
Code: [Select]
(strcat nil "1") is not valid.

So say, we set 'str' to an empty string:

 ...

This is EXACTLY where I was getting hung up too.  I didn't understand I needed a string first.  I WAS setting my list to an undefined variable and it kept erroring on me.

THANK YOU Lee for this magnificent explanation.
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Hangman

  • Swamp Rat
  • Posts: 566
Re: Convert a List to a String ...
« Reply #14 on: May 26, 2010, 02:57:30 PM »
Lee already posted a great explanation, but I wrote this and got sidetracked, so I'm posting it anyway...

Code: [Select]
(defun foo (lst del / str)
  (setq str (car lst)) ; set string based on first item of list
  (foreach x (cdr lst) ; step through list (except first item, since we alreaded appended it to your string
    (setq str (strcat str del x)) ; append 'next' item in list to string (separated with deliminator)
  )
)
Now this is good stuff.  I interpret the last line differently, I see this:
Code: [Select]
(setq str (strcat str del x)) as setting the variable 'str' and appending to it with 'str', but deleting 'x', so you would end up with a result like this:  (if 'lst' had 'Layer-1', 'Layer-2', 'Layer-3', 'Layer-4')
Quote
Layer-1 Layer-1 Layer-1 Layer-1
Simply because there is no 'del' definition in the help file.  What is it, where did you get it, etc.
I would think the code would have to read like this:
Code: [Select]
(setq str ((strcat str) del x)) in order to get what you described, but appearently not.

Thank you for the notes Alan.
Hangman  8)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Drafting Board, Mechanical Arm, KOH-I-NOOR 0.7mm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~