Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate with zip(*list) unpacking mechanism in Julia?

In Python, I can loop through a 2 lists concurrently to extract ngrams as such:

>>> s = 'the lazy fox jumps over the brown dog'
>>> list(zip(*[s[i:] for i in range(2)]))
[('t', 'h'), ('h', 'e'), ('e', ' '), (' ', 'l'), ('l', 'a'), ('a', 'z'), ('z', 'y'), ('y', ' '), (' ', 'f'), ('f', 'o'), ('o', 'x'), ('x', ' '), (' ', 'j'), ('j', 'u'), ('u', 'm'), ('m', 'p'), ('p', 's'), ('s', ' '), (' ', 'o'), ('o', 'v'), ('v', 'e'), ('e', 'r'), ('r', ' '), (' ', 't'), ('t', 'h'), ('h', 'e'), ('e', ' '), (' ', 'b'), ('b', 'r'), ('r', 'o'), ('o', 'w'), ('w', 'n'), ('n', ' '), (' ', 'd'), ('d', 'o'), ('o', 'g')]
>>> list(map(''.join, zip(*[s[i:] for i in range(2)])))
['th', 'he', 'e ', ' l', 'la', 'az', 'zy', 'y ', ' f', 'fo', 'ox', 'x ', ' j', 'ju', 'um', 'mp', 'ps', 's ', ' o', 'ov', 've', 'er', 'r ', ' t', 'th', 'he', 'e ', ' b', 'br', 'ro', 'ow', 'wn', 'n ', ' d', 'do', 'og']

In Julia, I could do similar steps but I'm not sure how to piece them up like how I did with Python.

First I could generate the 2 lists that needs to be iterated simultaneously, so instead of the Python [s[i:] for i in range(2)], in Julia:

> s = "abc def ghi lmnopq"
> [s[i:end] for i in range(1,2)]
2-element Array{String,1}:
 "abc def ghi lmnopq"
 "bc def ghi lmnopq" 

And to iterate them simultaneously, I could do this:

> c1, c2 = [line[i:end] for i in range(1,2)]
> [i for i in zip(c1, c2)]
> [join(i) for i in zip(c1, c2)]

Is there an unpacking mechanism like zip(*list) in Julia? If so, how to avoid creating the c1, c2 before the last list comprehension in Julia?

like image 961
alvas Avatar asked Feb 07 '17 02:02

alvas


People also ask

What is* zip in Python?

Python's zip() function creates an iterator that will aggregate elements from two or more iterables. You can use the resulting iterator to quickly and consistently solve common programming problems, like creating dictionaries.

What does zip do in Julia?

zip orders the calls to its subiterators in such a way that stateful iterators will not advance when another iterator finishes in the current iteration. See also: enumerate , splat .

Why do you use the zip() method in Python?

zip() in Python Python zip() method takes iterable or containers and returns a single iterator object, having mapped values from all the containers. It is used to map the similar index of multiple containers so that they can be used just using a single entity.

Can I zip more than two lists Python?

The Python zip() function makes it easy to also zip more than two lists. This works exactly like you'd expect, meaning you just only need to pass in the lists as different arguments.


1 Answers

The equivalent operation is called splatting in Julia, and is represented by a trailing ellipsis. Here's a rough transliteration of your Python code:

julia> s = "the lazy fox jumps over the brown dog";
julia> collect(zip([s[i:end] for i in 1:2]...))
36-element Array{Tuple{Char,Char},1}:
 ('t', 'h')
 ('h', 'e')
 ('e', ' ')
 (' ', 'l')
 ('l', 'a')
 ('a', 'z')
 ⋮

julia> map(join, zip([s[i:end] for i in 1:2]...))
36-element Array{String,1}:
 "th"
 "he"
 "e "
 " l"
 "la"
 "az"
 ⋮

Note that the range function doesn't do what you think it does… and it's rarely used. Ranges are typically constructed with start:stop colon syntax.

You also need to be careful as Julia's strings are indexed by byte offsets, so using 1:2 will break with a unicode string. Instead, I'd just write out the zip arguments exactly and use Iterators.drop to skip the first character:

collect(zip(s, Iterators.drop(s, 1)))
join.(zip(s, Iterators.drop(s, 1)))
like image 117
mbauman Avatar answered Oct 22 '22 05:10

mbauman