Can LaTeX automatically itemize a list?

So I have a word list file in .txt format,

I want to edit it and enumerate them. But since the file runs into thousands of lines potentially, it would be a daunting task to do it manually. I wonder if it is possible to automatically enumerate all the words (and make other small repetitive changes to each word) and even better, randomize them.

N.B. I am not exactly sure if it is a task that can or should be done in LaTeX, so if not, I also welcome an alternative suggestion. Thanks in advance.

Edit: When I meant small repetitive change, I have in mind something like drawing a ____ after each word.

So essentially, I need LaTex to do three things:

1. read the file and itemize it
2. draw a line after every word
3. randomize the whole list.

Sorry, I should have formated my questions better.

• You can investigate about CSV files and LaTeX. Nov 17, 2020 at 8:36
• Unfortunately, I'm not exactly sure what you mean by "and make other small repetitive changes to each word". Maybe explain this a little further in order for us to add this to our answers.
– Sam
Nov 17, 2020 at 8:50
• Yes. I realize I should have been more specific. See the edited change. Maybe I should open a different thread to deal with the other two questions? Nov 17, 2020 at 9:01
• @jxhyc I updated my answer.
– Sam
Nov 17, 2020 at 9:53

I propose a solution using the csvsimple package.

\documentclass{article}
\usepackage{csvsimple}

\begin{filecontents}{list.csv}
religion
religious
rely
remain
\end{filecontents}

\begin{document}

\csvloop{
file = {list.csv},
before line = \item
}

\end{document}


Edit

In order to draw a line after the elements, use a \rule:

\documentclass{article}
\usepackage{csvsimple}

\begin{filecontents}{list.csv}
religion
religious
rely
remain
\end{filecontents}

\begin{document}

\csvloop{
file = {list.csv},
before line = \item,
after line = \rule{1cm}{.4pt}
}

\end{document}


As LaTeX does not store the individual items of an enumerate, it's tricky to shuffle the items. There are some heavy solutions to this problem, but I wouldn't recommend any of them when handling large datasets ("thousands of lines potentially"). Just quickly set up a Python script to shuffle your list around before compiling your document.

import random

with open('data.csv', 'r') as input_file:

random.shuffle(data)

with open('output_file.csv', 'w') as output_file:
for item in data:
output_file.writelines(item)


You could even have a look at the pythontex package which enables you to add executable Python code to your LaTeX file. Upon document generation, the code will be executed and the results are added to the LaTeX file. I could imagine, that this would allow you to implement the shuffling to the document generation.

• The interface between TeX and simple scripting is one of the things I find hard to tackle. I'd love to see integrated solutions with python, PerlTeX, and, even more so, one with LuaTeX, especially including the shuffling, since csvsimple can't do it. Anyone? Nov 17, 2020 at 10:23
• @benjamin Have a look at the pythontex documentation. They nicely describe how to use Python within a LaTeX document.
– Sam
Nov 17, 2020 at 12:03

You can use \read to read a text file line by line

wordlist.txt

red
orange
yellow
green
blue
indigo
violet



file.tex

\documentclass{article}

\openin\wordlist=wordlist.txt
\begin{document}
\def\blankline{\par}

\begin{enumerate}
\loop\ifeof\wordlist
\else
\ifx\thisword\blankline
\else
\item \thisword
\fi
\repeat
\end{enumerate}
\end{document}


Since I've wanted to learn this for a while now, here a version of Sam's answer using LuaLaTeX. What I like about it is its being totally embedded in LaTeX, compiling in one shot with lualatex

\documentclass{article}
\usepackage{luacode}

\begin{filecontents*}{list.csv}
religion
religious
rely
remain
\end{filecontents*}

\begin{document}

\begin{itemize}

\begin{luacode}
io.input("list.csv")
-- use a table to store the lines of the file
local lines = {}
-- read the lines in table 'lines'
for line in io.lines() do
table.insert(lines, line)
end
-- use another table to store a shuffled version of lines
shuffled = {}
-- for each line, pickup a position in the shuffled table
-- and insert the line there
for i, line in ipairs(lines) do
local pos = math.random(1, #shuffled+1)
table.insert(shuffled, pos, line)
end

-- write all the lines, after an item and with a rule after it
for i, line in ipairs(shuffled) do
tex.sprint("\\item ", line, " \\rule{1cm}{.4pt}") end
\end{luacode}

\end{itemize}

\end{document}

• Nice! Lua looks much better than coding something like shuffling in TeX itself, with its crazy syntax. (Though I personally don't think I'll ever bother in the future coding anything within LaTeX documents at all – I find it to be a better solution to use a powerful language like Haskell or Python for generating the tex file in the first place, with 100% freedom for auto-generating content, and then it can be compiled with only xelatex or even pdflatex, which is still often a requirement for submitting papers etc..) Nov 18, 2020 at 12:46

LaTeX3 excels here in terms of elegance and brevity, I would say 😉:

\documentclass{article}
\usepackage{expl3}

\begin{filecontents*}{list.csv}
religion
religious
rely
remain
\end{filecontents*}

\begin{document}

\begin{itemize}

\ExplSyntaxOn
\seq_new:N\l_input_seq
\ior_new:N\l_file_stream
\ior_open:Nn\l_file_stream{list.csv}
\ior_str_map_inline:Nn\l_file_stream{ \seq_put_right:Nn\l_input_seq{#1} }
\ior_close:N\l_file_stream
\seq_shuffle:N\l_input_seq
\seq_map_inline:Nn\l_input_seq{\item~#1}
\ExplSyntaxOff

\end{itemize}

\end{document}

• I'm missing a winking face after "elegance and brevity" but +1 anyway ;-) Nov 17, 2020 at 16:11
• Added one for you ;-). Nov 17, 2020 at 16:19
• Technically, the other solutions require fewer lines and far less typing. Elegance in in the eye of the beholder. Nov 17, 2020 at 17:04
• Is there an introduction to latex3 for super dummies (not regular dummies :)? knowing that I am not familiar at all with tex plain stuff XD
– Diaa
Nov 18, 2020 at 15:19
• I drew all my knowledge from texdoc interface3. Nov 18, 2020 at 15:42

Sam told me to investigate pythontex, so here's the result: a solution embedding the python code in the LaTeX file. I think it's a good thing to have different solutions to the problem of interfacing LaTeX with scripting/programming, so one can pick their favourite one.

Compile in 3 steps:

1. *LaTeX myfile
2. pythontex myfile
3. *LaTeX myfile

myfile.tex:

\documentclass{article}
\usepackage{pythontex}

\begin{filecontents*}{list.csv}
religion
religious
rely
remain
\end{filecontents*}

\begin{document}

\begin{pycode}
import random

with open('list.csv', 'r') as input_file:

random.shuffle(data)

print(r'\begin{enumerate}')
for item in data:
print(r'\item ', item, r'\rule{1cm}{.4pt}')
print(r'\end{enumerate}')
\end{pycode}

\end{document}

• I think this is, by far, the best solution. Python is the correct choice for such a task. It is a superior language with an easy-to-read syntax. Although it is not really complicated to shuffle a list around, we saw that this easy task is rather complicated to do in pure LaTeX. With the development of LaTeX3 this gets a lot simpler, i.e. shorter, but it's still unreadable as we see in AlexG's answer. Python is well suited for data manipulation, and I think that we should use the most suited languages for any task. LaTeX is for typesetting, Python for data manipulation.
– Sam
Nov 19, 2020 at 8:40