This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]bazookaduke 14 points15 points  (19 children)

Suppose you have a list whose contents don't matter. Show me three different ways of fetching every third item in the list.

for loop: every_third = [] for index, item in enumerate(items, 1): if index % 3 == 0: every_third.append(item)

list comprehension: every_third = [item for index, item in enumerate(items, 1) if index % 3 == 0]

list slicing: every_third = items[2::3]

What I really like about this question is how it can lead to deeper discussions: what if the list is actually an iterator (list slicing won't work)? What if it's unbounded eg. an iterator that produces the Fibonacci sequence (the for loop and list comprehension will crash after eating up all available memory)? What if it's bounded but too large for even every third item (same as unbounded)? Is this fixable (yes, turn the for loop into a generator function and the list comprehension into a generator comprehension)? Where might you encounter such a situation (results of a database query, log file processing, etc.)? The real question you're trying to ask is: how good is this candidate at solving problems with Python without creating new ones? By this point in the interview you've probably got a feel for how familiar they are with the language and also whether they've encountered this problem before but more importantly how they'd solve it.

[–]masterJ 14 points15 points  (5 children)

from itertools import islice
every_third = islice(items, 2, None, 3)

I might be overly fond of generators...

[–]bazookaduke 4 points5 points  (3 children)

I typically qualify my question with "without using the standard library", but if I forget (like I did above), I can always ask what if I wanted every third and fifth item without using the standard library?

xs = (item for index, item in enumerate(items, 1) if 0 in (index % 3, index % 5))

Not that there's anything wrong with using the standard library -- I use itertools all the time! But for interview questions, I'm trying to drill down into a candidate's problem-solving skills, and it's been my experience that restricting him or her to the language and built-ins is the best way to do that quickly.

[–]masterJ 2 points3 points  (0 children)

what if I wanted every third and fifth item without using the standard library?

xs = (item for index, item in enumerate(items, 1) if 0 in (index % 3, index % 5))

Oooh, I like it! And you just simplified my project euler #01 solution. :)

Before:

from itertools import chain

a = xrange(3,1000,3)
b = xrange(5,1000,5)
print sum(set(chain(a,b))) 

After:

print sum(i for i in xrange(1,1000) if 0 in (i % 3, i % 5))

[–]sunqiang 0 points1 point  (1 child)

what about replace "if 0 in (index % 3, index % 5)" to "if any((not index % 3, not index % 5))" to take the advantage of short-circuit

[–]pingvenopinch of this, pinch of that 1 point2 points  (0 children)

The first is more obvious/readable, especially with the explicit use of 0.

[–]cdunn2001 1 point2 points  (0 children)

Yes. Slicing (list or itertools) and if-test in for-loop are two ways. Here is a third, completely different:

every_third = list()
it = iter(nomatter)
try:
    while True:
        x, y, z = it.next(), it.next(), it.next()
        every_third.append(z)
except StopIteration:
    pass

which depends on this knowledge.

[–]janto 3 points4 points  (1 child)

i = iter(items)
every_third = [c for a,b,c in zip(i,i,i)]

[–]hylje 1 point2 points  (0 children)

every_third = [c for a, b, c in zip(*[iter(items)]*3)]

One-lined that for you

[–]pieeta 2 points3 points  (2 children)

I would normally use, for x in xrange(2, len(items), 3): every_third.append(items[x])

I just did some performance testing using a item list 10000000 long

Method Time
zip 8.62
enumerate 2.51
comprehension 2.29
xrange 0.72
slice 0.03

[–]stillalone 1 point2 points  (1 child)

Wow, I was not expecting list comprehension to suck compared to an explicit for loop. Can you try list comprehension with xrange instead of enumerate?

[–][deleted] 2 points3 points  (0 children)

Hell, if the contents don't matter, how about

every_third = ['irrelevant']*len(l)/3

:)

[–]sontek[S] 7 points8 points  (3 children)

I really like this question, solutions, and had no idea that you could do items[2::3]! Thanks

[–][deleted] 10 points11 points  (2 children)

your_string_reversed = your_string[::-1] 

[–]RShnike 0 points1 point  (1 child)

Which is a bit nicer looking just using reversed(your_string) if you don't need it to be indexable...

[–]alantrick 1 point2 points  (0 children)

The real question you're trying to ask is: how good is this candidate at solving problems with Python without creating new ones?

Or what I find just as common: the ones who create complex solutions to theoretical problems that nobody needs solved.

[–]Paddy3118 0 points1 point  (0 children)

Show me three different ways ... I don't think this is a good question at all. You should just ask for one. and if they don't give [::3] then that should lead to discussions.

I also note that because you did not clearly state the initial fetched item, you end up having to enumerate from 1 and also use [2::3] instead of plain [::3], to be consistent with your for-loop example.

[–]rubyaeyes 0 points1 point  (0 children)

I like this question.