I have the following JSON:
{
"items": [
{
"item": "abc",
"status": "ready"
},
{
"item": "def",
"status": "ready"
},
{
"item": "ghi",
"status": "done",
"items": [
{
"item": "ABC",
"status": "ready"
},
{
"item": "DEF",
"status": "ready"
},
{
"item": "GHI",
"status": "done"
}
]
}
]
}
which I would like to convert to:
\begin{itemize}
\item abc\hfill{}ready
\item def\hfill{}ready
\item ghi\hfill{}done
\begin{itemize}
\item ABC\hfill{}ready
\item DEF\hfill{}ready
\item GHI\hfill{}done
\end{itemize}
\end{itemize}
The items
can be nested arbitrarily deep. I have the following Python code:
import json
import os
TAB = ' '
BEGIN = '\\begin{itemize}'
ITEM = '\\item {0}\\hfill{{}}{1}'
END = '\\end{itemize}'
def main(path):
with open(os.path.join(path, 'test.json')) as data_file:
data = json.load(data_file)
print('\n'.join(convert(data)))
def convert(data):
stack = [data['items'].__iter__()]
yield (TAB * (len(stack) - 1)) + BEGIN
while len(stack) > 0:
iterator = stack[len(stack) - 1]
try:
current = iterator.next()
yield (TAB * (len(stack) - 1)) + ITEM.format(current['item'], current['status'])
try:
stack.append(current['items'].__iter__())
yield (TAB * (len(stack) - 1)) + BEGIN
except KeyError:
pass
except StopIteration:
yield (TAB * (len(stack) - 1)) + END
stack.pop()
I am new to Python and am looking for suggestions for the code to be more idiomatic Python.
1 Answer 1
Unless you specifically want a tab of 2 spaces in the resulting LaTeX, you can use '\t'
to get the actual tab character.
TAB = '\t'
When working with strings with one or more backslashes, you can declare them as 'raw' strings by prefixing them with an r
, which allows you to write backslash characters without having to escape them.
BEGIN = r'\begin{itemize}'
ITEM = r'\item {0}\hfill{{}}{1}'
END = r'\end{itemize}'
You can use the magic method iter() to get iterators, for example:
stack = [iter(data['items'])]
or
stack.append(iter(current['items']))
This is more idiomatic than calling the __iter__()
method directly. In addition, there is a next()
magic method as well which you can use to get the next item from an iterator.
current = next(iterator)
If you are using Python 3.4 or higher, I'd recommend checking out the pathlib
module for manipulating file paths over os.path
, but in this case using os.path
does the job and is probably sufficient.
Explore related questions
See similar questions with these tags.