LaTeX può classificare automaticamente un elenco?

Nov 17 2020

Quindi ho un file di elenco di parole in .txtformato,

Voglio modificarlo ed enumerarli. Ma poiché il file corre potenzialmente su migliaia di righe, sarebbe un compito arduo farlo manualmente. Mi chiedo se sia possibile enumerare automaticamente tutte le parole (e apportare altre piccole modifiche ripetitive a ciascuna parola) e ancora meglio, randomizzarle.

NB Non sono esattamente sicuro se sia un'attività che può o deve essere eseguita in LaTeX, quindi in caso contrario, accolgo con favore anche un suggerimento alternativo. Grazie in anticipo.

Modifica: quando intendevo piccoli cambiamenti ripetitivi, ho in mente qualcosa come disegnare un ____ dopo ogni parola.

Quindi, in sostanza, ho bisogno che LaTex faccia tre cose:

  1. leggere il file e specificarlo
  2. traccia una linea dopo ogni parola
  3. randomizza l'intero elenco.

Scusa, avrei dovuto formulare meglio le mie domande.

Risposte

31 DavidCarlisle Nov 17 2020 at 15:22

È possibile utilizzare \readper leggere un file di testo riga per riga

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

Propongo una soluzione utilizzando il csvsimplepacchetto.

\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}

modificare

Per disegnare una linea dopo gli elementi, usa \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}

Poiché LaTeX non memorizza i singoli elementi di un'enumerazione, è difficile mescolare gli elementi. Esistono alcune soluzioni pesanti a questo problema, ma non ne consiglierei nessuna quando si gestiscono set di dati di grandi dimensioni ("migliaia di righe potenzialmente"). Basta impostare rapidamente uno script Python per mescolare l'elenco prima di compilare il 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)

Potresti anche dare un'occhiata al pythontexpacchetto che ti consente di aggiungere codice Python eseguibile al tuo file LaTeX. Alla generazione del documento, il codice verrà eseguito ei risultati verranno aggiunti al file LaTeX. Potrei immaginare, che questo ti permetterebbe di implementare il mescolamento alla generazione del documento.

10 benjamin Nov 17 2020 at 20:54

Dato che volevo imparare questo da un po 'di tempo, ecco una versione della risposta di Sam usando LuaLaTeX. Quello che mi piace è che è totalmente integrato in LaTeX, compilando in un colpo solo conlualatex

\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 eccelle qui in termini di eleganza e brevità, direi 😉:

\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 mi ha detto di indagare pythontex, quindi ecco il risultato: una soluzione che incorpora il codice python nel file LaTeX. Penso che sia una buona cosa avere diverse soluzioni al problema dell'interfacciamento di LaTeX con lo scripting / programmazione, in modo che si possa scegliere la propria preferita.

Compila in 3 passaggi:

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

miofile.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}