4 ms·
If you're aiming for idiomatic on 6 you don't do: def contains_duplicate(array): return sum([sum([1 if a_i-rot_ij else 0 for a
by crdoconnor 9y ago
If you're aiming for idiomatic on 6 you don't do:
def contains_duplicate(array):
return sum([sum([1 if a_i-rot_ij else 0
for a_i, rot_ij in zip(array, rot_i)])
for rot_i in [array[i:] + array[:i]
for i in range(1, len(array))]]
) != len(array) * (len(array) - 1)
OR:
def contains_duplicate(array):
for i in range(len(array)):
for j in range(i):
if array[i] == array[j]:
return True
return False
You do:
def contains_duplicate(array)
return len(set(array)) < len(array)
Or, if you can't hash the items:
def contains_duplicate(array):
any(len([y for y in items if x == y]) > 1 for x in items)
FWIW, I don't think I've ever seen an example where the cleanest (list | generator) comprehension is less clear than the cleanest equivalent for loop. I don't believe one exists.
So I think the examples are contrived and the 'rule' is bullshit.
- LyndsySimon 9y ago> FWIW, I don't think I've ever seen an example where the cleanest (list | generator) comprehension is less clear than the cleanest equivalent for loop. I don't believe one exists. Interesting. I'm not sure if I agree or disagree. I think the primary benefit of a comprehension is that it can be considered as a "unit", and you don't have to think about the iteration as fully to understand what's happening. As soon as "what's happening" gets more than minimally complex, that advantage is lost. Generator comprehensions should be much more clear and concise than their equivalent implementations using generator functions, though. If I remember this evening, I'm going to go through my code library and see if I can find something that will satisfy your challenge :)
- crdoconnor 9y agoI consider it an instance of https://en.wikipedia.org/wiki/Rule_of_least_power https://en.wikipedia.org/wiki/Rule_of_least_power List comprehensions are less expressive than for loops hence there is less to reason about. Hence, if what you want is achievable with a list comprehension, its intent will naturally be clearer than the for loop equivalent. ...provided you don't make it intentionally obtuse like the OP did.
- pvg 9y agoThat's not equivalent code. Your version only works with a list of hashable objects. Try it with a list of lists.
- deleted 9y ago[deleted]
- pvg 9y agoYou deleted your other comment but you've now written the comprehension version twice (the second version added in an edit when it was pointed out the first one isn't equivalent to the loop) and neither of them actually work. So perhaps writing the comprehension version is neither as clear or simple as you suggest.
- crdoconnor 9y agoIt was sloppy copying and pasting of a working expression. I think it's pretty clear I meant to write this: def contains_duplicate(array): return any(len([y for y in array if x == y]) > 1 for x in array) Or were you saying that this ^^ doesn't work?
- wcarss 9y agoIn my opinion, the non-hashable version which you moved here from a now-deleted response below is a perfect example of code that is harder to read, harder to hold in one's head, and most importantly harder to modify. The most pythonic version (your set solution) has a bug in that it does not apply to the general case. The second-most pythonic version (your one liner double for-loop slam dunk) is as clever as we can make it, and thereby fails Kernighan's debugging test[1]. I feel that one for loop inside another is fine. Everyone in every language can see it and know instantly what the run-time characteristics likely are, and what at each point it is doing. What's most important: if it ever seems to be broken, I can drop a debugger or a logger (maybe with a condition!) in at any point, with ease. There is a reason that pattern is nearly universally known, and imo it's that it is a good one. 1 - "Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?", https://en.m.wikiquote.org/wiki/Brian_Kernighan https://en.m.wikiquote.org/wiki/Brian_Kernighan
- crdoconnor 9y ago>is a perfect example of code that is harder to read, harder to hold in one's head, and most importantly harder to modify. It's both shorter and less expressive than the equivalent for loop. If you find it harder to read that says more about your familiarity with list and generator comprehensions. >The most pythonic version (your set solution) has a bug Not in lieu of a hard requirement for counting non-hashable items, it isn't. It's faster as well as simpler: O(n) instead of O(n2). Unless you're counting lists of lists or something it makes no sense not to use it. >I feel that one for loop inside another is fine. Everyone in every language can see it and know instantly what the run-time characteristics likely are, and what at each point it is doing. What's most important: if it ever seems to be broken, I can drop a debugger or a logger (maybe with a condition!) in at any point, with ease Writing your code in a more verbose and complex way in order to satisfy your desire to put a debugger in is by far and away not the most important aspect of clean coding.