Windowing Python Lists
━━━━━━━━━━━━━━━━━━━━━━
In python data science we often will reach for pandas a bit more than necessary. While pandas can save us so much there are times where there are...
Date: December 10, 2020
In python data science we often will reach for pandas a bit more than necessary. While pandas can save us so much there are times where there are alternatives that are much simpler. The itertools[38;2;189;147;249mand[0mmore-itertools` are full of cases of this.
This post is a walkthrough of me solving a problem with [38;2;189;147;249mmore-itertools[0m rather than reaching for a for loop, or pandas.
I am working on a one-line-link expander for my blog. I ended up doing it, just by modifying the markdown with python. I first split the post into lines with [38;2;189;147;249mcontent.split('\n')[0m, then look to see if the line appears to be just a link. One more safety net that I wanted to add was to check if there was whitespace around the line, this could not simply be done in a list comprehension by itself. I need just a bit of knowledge of the surrounding lines, enter [38;2;189;147;249mmore-itertools[0m.
[1m[38;2;189;147;249msimplified rendering function[0m
[38;2;68;71;90m─────────────────────────────[0m
I have a function that will check to see if the line should be expanded, then render the correct template. Fist step is to check if the line contains no spaces and starts with [38;2;189;147;249mhttps[0m, if it does render the template.
The real expand_line function uses requests to pull some metadata about the post to insert into the card, more on that in another post.
[38;2;248;248;242m[code][0m
def expand_line(line):
"""
Check if line should be expanded then render a template
"""
if ' ' in line and line.startswith('https'):
return line
return f""
[1m[38;2;189;147;249minitial implementation[0m
[38;2;68;71;90m──────────────────────[0m
My first implementation was to load in the content as a single string and use a list comprehension to expand each line.
[38;2;248;248;242m[code][0m
expanded_content = "\n".join(
[expand_line(line) for line in content]
)
[1m[38;2;189;147;249mThe issue[0m
[38;2;68;71;90m─────────[0m
Sometimes I write my posts in vim without wordwrap on and just use [38;2;189;147;249mgq[0m to wrap them to the current [38;2;189;147;249mtextwidth[0m. If I have a link that happens to be really long it ends up on its own line. I do not want one line links to expand if they are in the middle of a paragraph.
[38;2;248;248;242m[code][0m
## sample paragraph
This is a paragraph that has a really long link
[[ not-a-real-link-just-a-silly-example-for-this-post ]]
inside of it that ends up on its own line
[38;2;248;248;242m│ [0mI need a bit of knowledge about the lines around the link.
[1m[38;2;189;147;249mwindowing[0m
[38;2;68;71;90m─────────[0m
[38;2;189;147;249mmore-itertools[0m comes with a windowing function that will slide over an iterable with a width of n.
[38;2;248;248;242m[code][0m
[38;2;255;121;198m>>[0m[38;2;255;121;198m>[0m[38;2;248;248;242m [0m[38;2;248;248;242mfrom[0m[38;2;248;248;242m [0m[38;2;248;248;242mmore_itertools[0m[38;2;248;248;242m [0m[38;2;248;248;242mimport[0m[38;2;248;248;242m [0m[38;2;248;248;242mwindowed[0m[38;2;248;248;242m[0m
[38;2;255;121;198m>>[0m[38;2;255;121;198m>[0m[38;2;248;248;242m [0m[38;2;248;248;242mall_windows[0m[38;2;248;248;242m [0m[38;2;255;121;198m=[0m[38;2;248;248;242m [0m[38;2;248;248;242mwindowed[0m[38;2;248;248;242m([0m[38;2;248;248;242m[[0m[38;2;189;147;249m1[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m2[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m3[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m4[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m5[0m[38;2;248;248;242m][0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m3[0m[38;2;248;248;242m)[0m[38;2;248;248;242m[0m
[38;2;255;121;198m>>[0m[38;2;255;121;198m>[0m[38;2;248;248;242m [0m[38;2;248;248;242mlist[0m[38;2;248;248;242m([0m[38;2;248;248;242mall_windows[0m[38;2;248;248;242m)[0m[38;2;248;248;242m[0m
[38;2;248;248;242m[0m
[38;2;255;121;198m<[0m[38;2;255;121;198m![0m[38;2;255;121;198m-[0m[38;2;255;121;198m-[0m[38;2;248;248;242mmarkata[0m[38;2;255;121;198m-[0m[38;2;248;248;242mattribution[0m[38;2;255;121;198m-[0m[38;2;255;121;198m-[0m[38;2;255;121;198m>[0m[38;2;248;248;242m[0m
[38;2;248;248;242m[[0m[38;2;248;248;242m([0m[38;2;189;147;249m1[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m2[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m3[0m[38;2;248;248;242m)[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;248;248;242m([0m[38;2;189;147;249m2[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m3[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m4[0m[38;2;248;248;242m)[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;248;248;242m([0m[38;2;189;147;249m3[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m4[0m[38;2;248;248;242m,[0m[38;2;248;248;242m [0m[38;2;189;147;249m5[0m[38;2;248;248;242m)[0m[38;2;248;248;242m][0m[38;2;248;248;242m)[0m[38;2;248;248;242m][0m
[38;2;248;248;242m│ [0mthis example is copied from the [4m[38;2;248;248;242mmore-itertools docs[0m <[38;2;248;248;242mhttps://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.windowed[0m>
[1m[38;2;189;147;249msliding through my content[0m
[38;2;68;71;90m──────────────────────────[0m
The one extra that we need is padding at the front and back of the list so that we ensure that every value ends up in the middle position at least once.
[38;2;248;248;242m[code][0m
expanded_content = "\n".join(
[expand_line(*line) for line in windowed(f'\n{content}\n', 3)]
)
[1mmeta[0m: 👇 This is an example of a one-line-link card that we are trying to achieve.
understanding python \*args and \*\*kwargs Python and are super useful tools, that when used properly can make you code much simpler and easier to maintain. Large manual conversions from a dataset to... Jun 10, 2020
[38;2;248;248;242m│ [0mNot sure what *line is, check out this article.
[1m[38;2;189;147;249mupdate expand_line[0m
[38;2;68;71;90m──────────────────[0m
Now that we are calling [38;2;189;147;249mexpand_line[0m with all three lines. We need to update the function signature and add a guarding clause to return early if before or after lines are not blank.
[38;2;248;248;242m[code][0m
def expand_line(before, line, after):
"""
Check if line should be expanded then render a template
"""
if before != '' and after != '':
return line
if ' ' in line and line.startswith('https'):
return line
return f""
Hope you liked this walk-through of solving a problem I had with [38;2;189;147;249mmore-itertools[0m, If you learned something be sure to share it.