Formatting output for newcommand with for loop












2















I have the following minimum example



documentclass[12pt]{article}
usepackage{pgffor}

newcommand{formatlist}[2]{ {x^#1} foreach x in {#2} {,x^x}}
begin{document}
$$formatlist{5}{6,7}$$
end{document}


The foreach loop creates what I want to output, however, in order to prevent having an extra comma somewhere, I had to incorporate a second argument to get the formatting right. Does someone know how to do this with a single argument? If there's a way to splice a given argument into two lists then this would be a simple fix, but I couldn't figure out how to do that.










share|improve this question



























    2















    I have the following minimum example



    documentclass[12pt]{article}
    usepackage{pgffor}

    newcommand{formatlist}[2]{ {x^#1} foreach x in {#2} {,x^x}}
    begin{document}
    $$formatlist{5}{6,7}$$
    end{document}


    The foreach loop creates what I want to output, however, in order to prevent having an extra comma somewhere, I had to incorporate a second argument to get the formatting right. Does someone know how to do this with a single argument? If there's a way to splice a given argument into two lists then this would be a simple fix, but I couldn't figure out how to do that.










    share|improve this question

























      2












      2








      2








      I have the following minimum example



      documentclass[12pt]{article}
      usepackage{pgffor}

      newcommand{formatlist}[2]{ {x^#1} foreach x in {#2} {,x^x}}
      begin{document}
      $$formatlist{5}{6,7}$$
      end{document}


      The foreach loop creates what I want to output, however, in order to prevent having an extra comma somewhere, I had to incorporate a second argument to get the formatting right. Does someone know how to do this with a single argument? If there's a way to splice a given argument into two lists then this would be a simple fix, but I couldn't figure out how to do that.










      share|improve this question














      I have the following minimum example



      documentclass[12pt]{article}
      usepackage{pgffor}

      newcommand{formatlist}[2]{ {x^#1} foreach x in {#2} {,x^x}}
      begin{document}
      $$formatlist{5}{6,7}$$
      end{document}


      The foreach loop creates what I want to output, however, in order to prevent having an extra comma somewhere, I had to incorporate a second argument to get the formatting right. Does someone know how to do this with a single argument? If there's a way to splice a given argument into two lists then this would be a simple fix, but I couldn't figure out how to do that.







      macros foreach pgffor






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Feb 10 at 21:38









      Scott WhiteScott White

      132




      132






















          2 Answers
          2






          active

          oldest

          votes


















          2














          Welcome to TeX.SE! foreach allows you to see the count of an item, and ifnum can be used to distinguish between comma and no comma.



          documentclass[12pt]{article}
          usepackage{pgffor}

          newcommand{formatlist}[1]{foreach X [count=Y] in {#1} {ifnumY=1
          x^X
          else
          ,x^X
          fi}}
          begin{document}
          [formatlist{5,6,7}]
          end{document}


          enter image description here






          share|improve this answer
























          • Thanks! The count part really helps :)

            – Scott White
            Feb 10 at 22:13











          • @ScottWhite You're welcome! Please consider trading $$ ... $$ for [ ... ].

            – marmot
            Feb 10 at 22:14











          • thanks for the reference!

            – Scott White
            Feb 10 at 22:18








          • 1





            You can move x^X outside the branch: ifnumY=1else,fi x^X

            – Henri Menke
            Feb 11 at 1:05











          • @HenriMenke You are right, thanks! (However, the point of this answer was more to say there is the count option and ifnum to distinguish the first element from the rest.)

            – marmot
            Feb 11 at 1:10



















          1














          You can accommodate both lists and ranges. I also added an optional argument to change the base.



          The idea is that if the mandatory argument contains .., then it denotes a range. Otherwise it is supposed to be a list (with comma separators). In both cases the first term is detached and the others are printed with a comma before them.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn
          NewDocumentCommand{formatlist}{ O{x} >{SplitArgument{1}{..}}m }
          {
          scott_format_rangeorlist:nnn {#1} #2
          }

          seq_new:N l__scott_format_list_seq
          tl_new:N l__scott_format_list_tl

          cs_new_protected:Nn scott_format_rangeorlist:nnn
          {
          tl_if_novalue:nTF { #3 }
          {% no range, assume list of values
          scott_format_list:nn { #1 } { #2 }
          }
          {% range
          scott_format_range:nnn { #1 } { #2 } { #3 }
          }
          }

          cs_new_protected:Nn scott_format_list:nn
          {
          seq_set_from_clist:Nn l__scott_format_list_seq { #2 }
          seq_pop_left:NN l__scott_format_list_seq l__scott_format_list_tl
          % print the first term
          #1^{l__scott_format_list_tl}
          % print the other terms, with a comma
          seq_map_inline:Nn l__scott_format_list_seq { , #1^{##1} }
          }

          cs_new_protected:Nn scott_format_range:nnn
          {
          #1^{#2}
          int_step_inline:nnn { #2 + 1 } { #3 } { ,#1^{##1} }
          }
          ExplSyntaxOff

          begin{document}

          textbf{Ranges}

          $formatlist{5..7}$

          $formatlist{1..10}$

          $formatlist[y]{3}$

          $formatlist[z]{1..5}$

          $formatlist{8..8}$

          textbf{Lists}

          $formatlist{2,3,4,6}$

          $formatlist{2}$

          $formatlist[y]{6,8,10}$

          end{document}


          enter image description here




          1. The command formatlist is declared to have an optional argument, with default value x, and a mandatory argument; due to the “preprocessor” SplitArgument{1}{..}, this argument will be returned in the format {<A>}{<B>}, where <A> represents what comes before .. and <B> what's after; in the case .. doesn't appear, <B> will be something that will make the conditional if_novalue:nTF to return true.


          2. Control is then passed to scott_format_rangeorlist:nnn, which takes three arguments; #2 will consist of two braced items, as explained before.


          3. scott_format_rangeorlist:nnn examines the third argument; if it is the special item that makes if_novalue:nTF to return true, the first two arguments are passed to scott_format_list:nn (and #2 is so assumed to be a comma separated list), otherwise scott_format_range:nnn is called.


          4. scott_format_list:nn changes the comma separated list into a sequence, whose left item is then detached for being processed on its own and stored in a token list variable; then this first item is passed as exponent to #1 (the base); next the sequence is mapped to print ,#1^{##1}. In this context, ##1 represents the current item in the sequence.


          5. scott_format_range:nnn first prints #1^{#2} (here #2 is the lower bound in the range); then it does a loop printing ,#1^{##1} starting from #2+1 up to #3; here ##1 is the current integer in the loop.


          6. The function seq_map_inline:Nn loops over the sequence, executing each time the second argument with ##1 representing the current item.


          7. The function int_step_inline:nnn does a loop with step 1 from the integer given as first argument up to the integer given as second argument; each time the third argument is executed, with ##1 representing the current value.







          share|improve this answer


























          • Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)

            – Scott White
            Feb 10 at 22:28











          • @ScottWhite I added some explanations.

            – egreg
            Feb 11 at 0:19











          • Thanks for adding all the explanation!

            – Scott White
            yesterday











          Your Answer








          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "85"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f474237%2fformatting-output-for-newcommand-with-for-loop%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          Welcome to TeX.SE! foreach allows you to see the count of an item, and ifnum can be used to distinguish between comma and no comma.



          documentclass[12pt]{article}
          usepackage{pgffor}

          newcommand{formatlist}[1]{foreach X [count=Y] in {#1} {ifnumY=1
          x^X
          else
          ,x^X
          fi}}
          begin{document}
          [formatlist{5,6,7}]
          end{document}


          enter image description here






          share|improve this answer
























          • Thanks! The count part really helps :)

            – Scott White
            Feb 10 at 22:13











          • @ScottWhite You're welcome! Please consider trading $$ ... $$ for [ ... ].

            – marmot
            Feb 10 at 22:14











          • thanks for the reference!

            – Scott White
            Feb 10 at 22:18








          • 1





            You can move x^X outside the branch: ifnumY=1else,fi x^X

            – Henri Menke
            Feb 11 at 1:05











          • @HenriMenke You are right, thanks! (However, the point of this answer was more to say there is the count option and ifnum to distinguish the first element from the rest.)

            – marmot
            Feb 11 at 1:10
















          2














          Welcome to TeX.SE! foreach allows you to see the count of an item, and ifnum can be used to distinguish between comma and no comma.



          documentclass[12pt]{article}
          usepackage{pgffor}

          newcommand{formatlist}[1]{foreach X [count=Y] in {#1} {ifnumY=1
          x^X
          else
          ,x^X
          fi}}
          begin{document}
          [formatlist{5,6,7}]
          end{document}


          enter image description here






          share|improve this answer
























          • Thanks! The count part really helps :)

            – Scott White
            Feb 10 at 22:13











          • @ScottWhite You're welcome! Please consider trading $$ ... $$ for [ ... ].

            – marmot
            Feb 10 at 22:14











          • thanks for the reference!

            – Scott White
            Feb 10 at 22:18








          • 1





            You can move x^X outside the branch: ifnumY=1else,fi x^X

            – Henri Menke
            Feb 11 at 1:05











          • @HenriMenke You are right, thanks! (However, the point of this answer was more to say there is the count option and ifnum to distinguish the first element from the rest.)

            – marmot
            Feb 11 at 1:10














          2












          2








          2







          Welcome to TeX.SE! foreach allows you to see the count of an item, and ifnum can be used to distinguish between comma and no comma.



          documentclass[12pt]{article}
          usepackage{pgffor}

          newcommand{formatlist}[1]{foreach X [count=Y] in {#1} {ifnumY=1
          x^X
          else
          ,x^X
          fi}}
          begin{document}
          [formatlist{5,6,7}]
          end{document}


          enter image description here






          share|improve this answer













          Welcome to TeX.SE! foreach allows you to see the count of an item, and ifnum can be used to distinguish between comma and no comma.



          documentclass[12pt]{article}
          usepackage{pgffor}

          newcommand{formatlist}[1]{foreach X [count=Y] in {#1} {ifnumY=1
          x^X
          else
          ,x^X
          fi}}
          begin{document}
          [formatlist{5,6,7}]
          end{document}


          enter image description here







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Feb 10 at 21:47









          marmotmarmot

          101k4116224




          101k4116224













          • Thanks! The count part really helps :)

            – Scott White
            Feb 10 at 22:13











          • @ScottWhite You're welcome! Please consider trading $$ ... $$ for [ ... ].

            – marmot
            Feb 10 at 22:14











          • thanks for the reference!

            – Scott White
            Feb 10 at 22:18








          • 1





            You can move x^X outside the branch: ifnumY=1else,fi x^X

            – Henri Menke
            Feb 11 at 1:05











          • @HenriMenke You are right, thanks! (However, the point of this answer was more to say there is the count option and ifnum to distinguish the first element from the rest.)

            – marmot
            Feb 11 at 1:10



















          • Thanks! The count part really helps :)

            – Scott White
            Feb 10 at 22:13











          • @ScottWhite You're welcome! Please consider trading $$ ... $$ for [ ... ].

            – marmot
            Feb 10 at 22:14











          • thanks for the reference!

            – Scott White
            Feb 10 at 22:18








          • 1





            You can move x^X outside the branch: ifnumY=1else,fi x^X

            – Henri Menke
            Feb 11 at 1:05











          • @HenriMenke You are right, thanks! (However, the point of this answer was more to say there is the count option and ifnum to distinguish the first element from the rest.)

            – marmot
            Feb 11 at 1:10

















          Thanks! The count part really helps :)

          – Scott White
          Feb 10 at 22:13





          Thanks! The count part really helps :)

          – Scott White
          Feb 10 at 22:13













          @ScottWhite You're welcome! Please consider trading $$ ... $$ for [ ... ].

          – marmot
          Feb 10 at 22:14





          @ScottWhite You're welcome! Please consider trading $$ ... $$ for [ ... ].

          – marmot
          Feb 10 at 22:14













          thanks for the reference!

          – Scott White
          Feb 10 at 22:18







          thanks for the reference!

          – Scott White
          Feb 10 at 22:18






          1




          1





          You can move x^X outside the branch: ifnumY=1else,fi x^X

          – Henri Menke
          Feb 11 at 1:05





          You can move x^X outside the branch: ifnumY=1else,fi x^X

          – Henri Menke
          Feb 11 at 1:05













          @HenriMenke You are right, thanks! (However, the point of this answer was more to say there is the count option and ifnum to distinguish the first element from the rest.)

          – marmot
          Feb 11 at 1:10





          @HenriMenke You are right, thanks! (However, the point of this answer was more to say there is the count option and ifnum to distinguish the first element from the rest.)

          – marmot
          Feb 11 at 1:10











          1














          You can accommodate both lists and ranges. I also added an optional argument to change the base.



          The idea is that if the mandatory argument contains .., then it denotes a range. Otherwise it is supposed to be a list (with comma separators). In both cases the first term is detached and the others are printed with a comma before them.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn
          NewDocumentCommand{formatlist}{ O{x} >{SplitArgument{1}{..}}m }
          {
          scott_format_rangeorlist:nnn {#1} #2
          }

          seq_new:N l__scott_format_list_seq
          tl_new:N l__scott_format_list_tl

          cs_new_protected:Nn scott_format_rangeorlist:nnn
          {
          tl_if_novalue:nTF { #3 }
          {% no range, assume list of values
          scott_format_list:nn { #1 } { #2 }
          }
          {% range
          scott_format_range:nnn { #1 } { #2 } { #3 }
          }
          }

          cs_new_protected:Nn scott_format_list:nn
          {
          seq_set_from_clist:Nn l__scott_format_list_seq { #2 }
          seq_pop_left:NN l__scott_format_list_seq l__scott_format_list_tl
          % print the first term
          #1^{l__scott_format_list_tl}
          % print the other terms, with a comma
          seq_map_inline:Nn l__scott_format_list_seq { , #1^{##1} }
          }

          cs_new_protected:Nn scott_format_range:nnn
          {
          #1^{#2}
          int_step_inline:nnn { #2 + 1 } { #3 } { ,#1^{##1} }
          }
          ExplSyntaxOff

          begin{document}

          textbf{Ranges}

          $formatlist{5..7}$

          $formatlist{1..10}$

          $formatlist[y]{3}$

          $formatlist[z]{1..5}$

          $formatlist{8..8}$

          textbf{Lists}

          $formatlist{2,3,4,6}$

          $formatlist{2}$

          $formatlist[y]{6,8,10}$

          end{document}


          enter image description here




          1. The command formatlist is declared to have an optional argument, with default value x, and a mandatory argument; due to the “preprocessor” SplitArgument{1}{..}, this argument will be returned in the format {<A>}{<B>}, where <A> represents what comes before .. and <B> what's after; in the case .. doesn't appear, <B> will be something that will make the conditional if_novalue:nTF to return true.


          2. Control is then passed to scott_format_rangeorlist:nnn, which takes three arguments; #2 will consist of two braced items, as explained before.


          3. scott_format_rangeorlist:nnn examines the third argument; if it is the special item that makes if_novalue:nTF to return true, the first two arguments are passed to scott_format_list:nn (and #2 is so assumed to be a comma separated list), otherwise scott_format_range:nnn is called.


          4. scott_format_list:nn changes the comma separated list into a sequence, whose left item is then detached for being processed on its own and stored in a token list variable; then this first item is passed as exponent to #1 (the base); next the sequence is mapped to print ,#1^{##1}. In this context, ##1 represents the current item in the sequence.


          5. scott_format_range:nnn first prints #1^{#2} (here #2 is the lower bound in the range); then it does a loop printing ,#1^{##1} starting from #2+1 up to #3; here ##1 is the current integer in the loop.


          6. The function seq_map_inline:Nn loops over the sequence, executing each time the second argument with ##1 representing the current item.


          7. The function int_step_inline:nnn does a loop with step 1 from the integer given as first argument up to the integer given as second argument; each time the third argument is executed, with ##1 representing the current value.







          share|improve this answer


























          • Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)

            – Scott White
            Feb 10 at 22:28











          • @ScottWhite I added some explanations.

            – egreg
            Feb 11 at 0:19











          • Thanks for adding all the explanation!

            – Scott White
            yesterday
















          1














          You can accommodate both lists and ranges. I also added an optional argument to change the base.



          The idea is that if the mandatory argument contains .., then it denotes a range. Otherwise it is supposed to be a list (with comma separators). In both cases the first term is detached and the others are printed with a comma before them.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn
          NewDocumentCommand{formatlist}{ O{x} >{SplitArgument{1}{..}}m }
          {
          scott_format_rangeorlist:nnn {#1} #2
          }

          seq_new:N l__scott_format_list_seq
          tl_new:N l__scott_format_list_tl

          cs_new_protected:Nn scott_format_rangeorlist:nnn
          {
          tl_if_novalue:nTF { #3 }
          {% no range, assume list of values
          scott_format_list:nn { #1 } { #2 }
          }
          {% range
          scott_format_range:nnn { #1 } { #2 } { #3 }
          }
          }

          cs_new_protected:Nn scott_format_list:nn
          {
          seq_set_from_clist:Nn l__scott_format_list_seq { #2 }
          seq_pop_left:NN l__scott_format_list_seq l__scott_format_list_tl
          % print the first term
          #1^{l__scott_format_list_tl}
          % print the other terms, with a comma
          seq_map_inline:Nn l__scott_format_list_seq { , #1^{##1} }
          }

          cs_new_protected:Nn scott_format_range:nnn
          {
          #1^{#2}
          int_step_inline:nnn { #2 + 1 } { #3 } { ,#1^{##1} }
          }
          ExplSyntaxOff

          begin{document}

          textbf{Ranges}

          $formatlist{5..7}$

          $formatlist{1..10}$

          $formatlist[y]{3}$

          $formatlist[z]{1..5}$

          $formatlist{8..8}$

          textbf{Lists}

          $formatlist{2,3,4,6}$

          $formatlist{2}$

          $formatlist[y]{6,8,10}$

          end{document}


          enter image description here




          1. The command formatlist is declared to have an optional argument, with default value x, and a mandatory argument; due to the “preprocessor” SplitArgument{1}{..}, this argument will be returned in the format {<A>}{<B>}, where <A> represents what comes before .. and <B> what's after; in the case .. doesn't appear, <B> will be something that will make the conditional if_novalue:nTF to return true.


          2. Control is then passed to scott_format_rangeorlist:nnn, which takes three arguments; #2 will consist of two braced items, as explained before.


          3. scott_format_rangeorlist:nnn examines the third argument; if it is the special item that makes if_novalue:nTF to return true, the first two arguments are passed to scott_format_list:nn (and #2 is so assumed to be a comma separated list), otherwise scott_format_range:nnn is called.


          4. scott_format_list:nn changes the comma separated list into a sequence, whose left item is then detached for being processed on its own and stored in a token list variable; then this first item is passed as exponent to #1 (the base); next the sequence is mapped to print ,#1^{##1}. In this context, ##1 represents the current item in the sequence.


          5. scott_format_range:nnn first prints #1^{#2} (here #2 is the lower bound in the range); then it does a loop printing ,#1^{##1} starting from #2+1 up to #3; here ##1 is the current integer in the loop.


          6. The function seq_map_inline:Nn loops over the sequence, executing each time the second argument with ##1 representing the current item.


          7. The function int_step_inline:nnn does a loop with step 1 from the integer given as first argument up to the integer given as second argument; each time the third argument is executed, with ##1 representing the current value.







          share|improve this answer


























          • Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)

            – Scott White
            Feb 10 at 22:28











          • @ScottWhite I added some explanations.

            – egreg
            Feb 11 at 0:19











          • Thanks for adding all the explanation!

            – Scott White
            yesterday














          1












          1








          1







          You can accommodate both lists and ranges. I also added an optional argument to change the base.



          The idea is that if the mandatory argument contains .., then it denotes a range. Otherwise it is supposed to be a list (with comma separators). In both cases the first term is detached and the others are printed with a comma before them.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn
          NewDocumentCommand{formatlist}{ O{x} >{SplitArgument{1}{..}}m }
          {
          scott_format_rangeorlist:nnn {#1} #2
          }

          seq_new:N l__scott_format_list_seq
          tl_new:N l__scott_format_list_tl

          cs_new_protected:Nn scott_format_rangeorlist:nnn
          {
          tl_if_novalue:nTF { #3 }
          {% no range, assume list of values
          scott_format_list:nn { #1 } { #2 }
          }
          {% range
          scott_format_range:nnn { #1 } { #2 } { #3 }
          }
          }

          cs_new_protected:Nn scott_format_list:nn
          {
          seq_set_from_clist:Nn l__scott_format_list_seq { #2 }
          seq_pop_left:NN l__scott_format_list_seq l__scott_format_list_tl
          % print the first term
          #1^{l__scott_format_list_tl}
          % print the other terms, with a comma
          seq_map_inline:Nn l__scott_format_list_seq { , #1^{##1} }
          }

          cs_new_protected:Nn scott_format_range:nnn
          {
          #1^{#2}
          int_step_inline:nnn { #2 + 1 } { #3 } { ,#1^{##1} }
          }
          ExplSyntaxOff

          begin{document}

          textbf{Ranges}

          $formatlist{5..7}$

          $formatlist{1..10}$

          $formatlist[y]{3}$

          $formatlist[z]{1..5}$

          $formatlist{8..8}$

          textbf{Lists}

          $formatlist{2,3,4,6}$

          $formatlist{2}$

          $formatlist[y]{6,8,10}$

          end{document}


          enter image description here




          1. The command formatlist is declared to have an optional argument, with default value x, and a mandatory argument; due to the “preprocessor” SplitArgument{1}{..}, this argument will be returned in the format {<A>}{<B>}, where <A> represents what comes before .. and <B> what's after; in the case .. doesn't appear, <B> will be something that will make the conditional if_novalue:nTF to return true.


          2. Control is then passed to scott_format_rangeorlist:nnn, which takes three arguments; #2 will consist of two braced items, as explained before.


          3. scott_format_rangeorlist:nnn examines the third argument; if it is the special item that makes if_novalue:nTF to return true, the first two arguments are passed to scott_format_list:nn (and #2 is so assumed to be a comma separated list), otherwise scott_format_range:nnn is called.


          4. scott_format_list:nn changes the comma separated list into a sequence, whose left item is then detached for being processed on its own and stored in a token list variable; then this first item is passed as exponent to #1 (the base); next the sequence is mapped to print ,#1^{##1}. In this context, ##1 represents the current item in the sequence.


          5. scott_format_range:nnn first prints #1^{#2} (here #2 is the lower bound in the range); then it does a loop printing ,#1^{##1} starting from #2+1 up to #3; here ##1 is the current integer in the loop.


          6. The function seq_map_inline:Nn loops over the sequence, executing each time the second argument with ##1 representing the current item.


          7. The function int_step_inline:nnn does a loop with step 1 from the integer given as first argument up to the integer given as second argument; each time the third argument is executed, with ##1 representing the current value.







          share|improve this answer















          You can accommodate both lists and ranges. I also added an optional argument to change the base.



          The idea is that if the mandatory argument contains .., then it denotes a range. Otherwise it is supposed to be a list (with comma separators). In both cases the first term is detached and the others are printed with a comma before them.



          documentclass{article}
          usepackage{xparse}

          ExplSyntaxOn
          NewDocumentCommand{formatlist}{ O{x} >{SplitArgument{1}{..}}m }
          {
          scott_format_rangeorlist:nnn {#1} #2
          }

          seq_new:N l__scott_format_list_seq
          tl_new:N l__scott_format_list_tl

          cs_new_protected:Nn scott_format_rangeorlist:nnn
          {
          tl_if_novalue:nTF { #3 }
          {% no range, assume list of values
          scott_format_list:nn { #1 } { #2 }
          }
          {% range
          scott_format_range:nnn { #1 } { #2 } { #3 }
          }
          }

          cs_new_protected:Nn scott_format_list:nn
          {
          seq_set_from_clist:Nn l__scott_format_list_seq { #2 }
          seq_pop_left:NN l__scott_format_list_seq l__scott_format_list_tl
          % print the first term
          #1^{l__scott_format_list_tl}
          % print the other terms, with a comma
          seq_map_inline:Nn l__scott_format_list_seq { , #1^{##1} }
          }

          cs_new_protected:Nn scott_format_range:nnn
          {
          #1^{#2}
          int_step_inline:nnn { #2 + 1 } { #3 } { ,#1^{##1} }
          }
          ExplSyntaxOff

          begin{document}

          textbf{Ranges}

          $formatlist{5..7}$

          $formatlist{1..10}$

          $formatlist[y]{3}$

          $formatlist[z]{1..5}$

          $formatlist{8..8}$

          textbf{Lists}

          $formatlist{2,3,4,6}$

          $formatlist{2}$

          $formatlist[y]{6,8,10}$

          end{document}


          enter image description here




          1. The command formatlist is declared to have an optional argument, with default value x, and a mandatory argument; due to the “preprocessor” SplitArgument{1}{..}, this argument will be returned in the format {<A>}{<B>}, where <A> represents what comes before .. and <B> what's after; in the case .. doesn't appear, <B> will be something that will make the conditional if_novalue:nTF to return true.


          2. Control is then passed to scott_format_rangeorlist:nnn, which takes three arguments; #2 will consist of two braced items, as explained before.


          3. scott_format_rangeorlist:nnn examines the third argument; if it is the special item that makes if_novalue:nTF to return true, the first two arguments are passed to scott_format_list:nn (and #2 is so assumed to be a comma separated list), otherwise scott_format_range:nnn is called.


          4. scott_format_list:nn changes the comma separated list into a sequence, whose left item is then detached for being processed on its own and stored in a token list variable; then this first item is passed as exponent to #1 (the base); next the sequence is mapped to print ,#1^{##1}. In this context, ##1 represents the current item in the sequence.


          5. scott_format_range:nnn first prints #1^{#2} (here #2 is the lower bound in the range); then it does a loop printing ,#1^{##1} starting from #2+1 up to #3; here ##1 is the current integer in the loop.


          6. The function seq_map_inline:Nn loops over the sequence, executing each time the second argument with ##1 representing the current item.


          7. The function int_step_inline:nnn does a loop with step 1 from the integer given as first argument up to the integer given as second argument; each time the third argument is executed, with ##1 representing the current value.








          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Feb 11 at 0:18

























          answered Feb 10 at 22:17









          egregegreg

          720k8719093208




          720k8719093208













          • Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)

            – Scott White
            Feb 10 at 22:28











          • @ScottWhite I added some explanations.

            – egreg
            Feb 11 at 0:19











          • Thanks for adding all the explanation!

            – Scott White
            yesterday



















          • Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)

            – Scott White
            Feb 10 at 22:28











          • @ScottWhite I added some explanations.

            – egreg
            Feb 11 at 0:19











          • Thanks for adding all the explanation!

            – Scott White
            yesterday

















          Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)

          – Scott White
          Feb 10 at 22:28





          Though the answer marmot gave was the type I was looking for with my simple case, as someone who also loves programming general functions, I love your solution as well! Though I'm new to this more advanced LaTeXing and so I'm not yet able to understand most of what's going on with your solution. That code would make for a great teaching example I think if you could add a few comments on the different commands you used in it to make it more understandable :)

          – Scott White
          Feb 10 at 22:28













          @ScottWhite I added some explanations.

          – egreg
          Feb 11 at 0:19





          @ScottWhite I added some explanations.

          – egreg
          Feb 11 at 0:19













          Thanks for adding all the explanation!

          – Scott White
          yesterday





          Thanks for adding all the explanation!

          – Scott White
          yesterday


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to TeX - LaTeX Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f474237%2fformatting-output-for-newcommand-with-for-loop%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          How to send String Array data to Server using php in android

          Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

          Is anime1.com a legal site for watching anime?