O LaTeX pode relacionar automaticamente uma lista?

Nov 17 2020

Tenho um arquivo de lista de palavras em .txtformato,

Quero editá-lo e enumerá-los. Mas, como o arquivo potencialmente tem milhares de linhas, seria uma tarefa difícil fazê-lo manualmente. Gostaria de saber se é possível enumerar automaticamente todas as palavras (e fazer outras pequenas alterações repetitivas para cada palavra) e ainda melhor, randomizá-las.

NB, não tenho certeza se é uma tarefa que pode ou deve ser feita em LaTeX, então se não, também agradeço uma sugestão alternativa. Desde já, obrigado.

Edit: Quando eu quis dizer pequenas mudanças repetitivas, tenho em mente algo como desenhar um ____ após cada palavra.

Então, essencialmente, eu preciso que o LaTex faça três coisas:

  1. leia o arquivo e especifique-o
  2. desenhe uma linha após cada palavra
  3. randomizar toda a lista.

Desculpe, eu deveria ter formatado melhor minhas perguntas.

Respostas

31 DavidCarlisle Nov 17 2020 at 15:22

Você pode usar \readpara ler um arquivo de texto linha por linha

wordlist.txt

red
orange
yellow
green
blue
indigo
violet

file.tex

\documentclass{article}

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

\begin{enumerate}
\loop\ifeof\wordlist
\else
\read\wordlist to \thisword
\ifx\thisword\blankline
\else
\item \thisword
\fi
\repeat
\end{enumerate}
\end{document}
18 Sam Nov 17 2020 at 15:40

Proponho uma solução usando o csvsimplepacote.

\documentclass{article}
\usepackage{csvsimple}

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

\begin{document}

\csvloop{
    file = {list.csv},
    no head,
    before reading = {\begin{enumerate}},
    after reading = {\end{enumerate}},
    before line = \item
}

\end{document}

Editar

Para desenhar uma linha após os elementos, use um \rule:

\documentclass{article}
\usepackage{csvsimple}

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

\begin{document}

\csvloop{
    file = {list.csv},
    no head,
    before reading = {\begin{enumerate}},
    after reading = {\end{enumerate}},
    before line = \item,
    after line = \rule{1cm}{.4pt}
}

\end{document}

Como o LaTeX não armazena os itens individuais de um enumerado, é complicado embaralhar os itens. Existem algumas soluções pesadas para esse problema, mas eu não recomendaria nenhuma delas ao lidar com grandes conjuntos de dados ("milhares de linhas potencialmente"). Basta configurar rapidamente um script Python para embaralhar sua lista antes de compilar seu documento.

import random

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

random.shuffle(data)

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

Você pode até dar uma olhada no pythontexpacote que permite adicionar código Python executável ao seu arquivo LaTeX. Após a geração do documento, o código será executado e os resultados serão adicionados ao arquivo LaTeX. Eu poderia imaginar que isso permitiria a você implementar o embaralhamento para a geração de documentos.

10 benjamin Nov 17 2020 at 20:54

Como queria aprender isso há algum tempo, aqui está uma versão da resposta de Sam usando LuaLaTeX. O que eu gosto nele é que ele está totalmente integrado ao LaTeX, compilando em uma única cena comlualatex

\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}
10 AlexG Nov 17 2020 at 23:05

LaTeX3 se destaca aqui em termos de elegância e brevidade, eu diria 😉:

\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}
4 benjamin Nov 19 2020 at 14:30

Sam me disse para investigar pythontex, então aqui está o resultado: uma solução incorporando o código Python no arquivo LaTeX. Eu acho que é uma coisa boa ter soluções diferentes para o problema de interface do LaTeX com script / programação, para que se possa escolher sua favorita.

Compile em 3 etapas:

  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:
    data = input_file.readlines()

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}