TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Is there a command/macro in latex to generate python-like dictionaries, i.e.

var = {a:1, b:2, c:3}

which then return for \var{b} 2?

share|improve this question
    
If you use numeric keys you can use the TeX primitive \ifcase ... \or: \def\var#1{\ifcase 1 a\or b\or c} – Andrew Cashner Mar 20 at 13:58
up vote 16 down vote accepted

You can emulate it with a property list:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\DefineDictionary}{mm}
 {
  \arclupus_dict_def:nn { #1 } { #2 }
 }

\seq_new:N \l__arclupus_dict_temp_seq

\cs_new_protected:Nn \arclupus_dict_def:nn
 {
  \prop_gclear_new:c { g_arclupus_#1_dict_prop }
  \clist_map_inline:nn { #2 }
   {
    \__arclupus_dict_add:nn { #1 } { ##1 }
   }
  \cs_new:cpn { #1 } ##1 { \prop_item:cn { g_arclupus_#1_dict_prop } { ##1 } }
 }

\cs_new_protected:Nn \__arclupus_dict_add:nn
 {
  \seq_set_split:Nnn \l__arclupus_dict_temp_seq { / } { #2 }
  \prop_gput:cxx { g_arclupus_#1_dict_prop }
   {
    \seq_item:Nn \l__arclupus_dict_temp_seq { 1 }
   }
   {
    \seq_item:Nn \l__arclupus_dict_temp_seq { 2 }
   }
 }
\cs_generate_variant:Nn \prop_gput:Nnn { cxx }
\ExplSyntaxOff

\DefineDictionary{var}{a/1, b/2, c/3}

\begin{document}

\var{a}

\var{c}

\var{b}

\end{document}

The \DefineDictionary takes as argument the dictionary name and the data. A new property list is created (or an existing one is cleared); then each item in the second argument is split at / to become an item in the property list. Finally, a macro with the name of the dictionary is created to retrieve the data.

The version with the colon is slightly trickier, because we can't use a literal : for the split operation.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\DefineDictionary}{mm}
 {
  \arclupus_dict_def:nn { #1 } { #2 }
 }

\seq_new:N \l__arclupus_dict_temp_seq

\cs_new_protected:Nn \arclupus_dict_def:nn
 {
  \prop_gclear_new:c { g_arclupus_#1_dict_prop }
  \clist_map_inline:nn { #2 }
   {
    \__arclupus_dict_add:nn { #1 } { ##1 }
   }
  \cs_new:cpn { #1 } ##1 { \prop_item:cn { g_arclupus_#1_dict_prop } { ##1 } }
 }

\cs_new_protected:Nn \__arclupus_dict_add:nn
 {
  \seq_set_split:NVn \l__arclupus_dict_temp_seq \c_colon_str { #2 }
  \prop_gput:cxx { g_arclupus_#1_dict_prop }
   {
    \seq_item:Nn \l__arclupus_dict_temp_seq { 1 }
   }
   {
    \seq_item:Nn \l__arclupus_dict_temp_seq { 2 }
   }
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
\cs_generate_variant:Nn \prop_gput:Nnn { cxx }
\ExplSyntaxOff

\DefineDictionary{var}{a:1, b:2, c:3}

\begin{document}

\var{a}

\var{c}

\var{b}

\end{document}

If you also need to pass macros to \var, then change the line

  \cs_new:cpn { #1 } ##1 { \prop_item:cn { g_arclupus_#1_dict_prop } { ##1 } }

into

  \cs_new:cpn { #1 } ##1 { \prop_item:cf { g_arclupus_#1_dict_prop } { ##1 } }

and add, just before \ExplSyntaxOff, the magic line

\cs_generate_variant:Nn \prop_item:Nn { cf }

that defines the required variant.

Macros that expand to strings are then welcome in the argument of the newly created macro (\var in the example). Note that \var is still fully expandable.

share|improve this answer
    
You could add the {a:1, b:2} version. With the recent (or not so recent) \char_generate:nn and a \seq_set_split:Nfn it's relatively simple. – Manuel Mar 20 at 0:12
    
@Manuel Done; no \char_generate:nn, though. ;-) – egreg Mar 20 at 0:17
    
I see it already exists :) – Manuel Mar 20 at 0:17
    
Going to test that, will report back, thanks! – arc_lupus Mar 20 at 0:18
1  
Is it possible to get \var{\mysinglelettermacro} working? Right now it just prints nothing. (Assuming the \var from the above MWE). – PTNobel Mar 20 at 5:24

FWIW, ConTeXt has built-in data-structure that is equivalent to a dictionary. In particular,

\setvariables
    [var]
    [
      a=1,
      b=2,
      c=3,
    ]

Then you can access the variables using \getvariable{var}{a}, etc.

Using \def\abc{a} \getvariable{var}{\abc} also works.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.