<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Tue, Jul 3, 2018 at 2:52 AM Chris Barker via Python-ideas <<a href="mailto:python-ideas@python.org">python-ideas@python.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div>I'd write: <br></div></div></div></blockquote><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div>    map(len, words)</div><div><br></div><div>But I'd also write</div><div>    [len(fullname) for fullname in contacts]</div></div></div></blockquote><div><br></div><font face="monospace, monospace">map(lambda name: name.first_name, all_names)</font><br><div>vs<br></div><div><span style="font-family:monospace,monospace">[name.first_name for nam in all names]</span><br></div><div><br></div><div>I
 really like the comprehension form much better when what you really 
want is a simple expression like an attribute access or index or simple 
calculation, or ....</div></div></div></div></div></blockquote><div><br></div><div>Why not `<font face="monospace, monospace">map(attrgetter('first_name'), all_names)</font>`?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div class="gmail_quote"><font face="monospace, monospace">In [56]: grouping(school_student_list)</font></div><div class="gmail_quote"><font face="monospace, monospace">Out[56]: {'SchoolA': ['Fred', 'Mary'], 'SchoolB': ['Bob', 'Jane'], 'SchoolC': ['Nancy']}</font></div></div></div></div></blockquote><div><br></div><div>This one case is definitely nice. However...</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">And here are the examples from the PEP:<font face="monospace, monospace"><br></font></div><div class="gmail_quote"><font face="monospace, monospace">(untested -- I may hav missed some brackets, etc)<br></font></div></div></div></blockquote><div><br></div><div>What you've missed, in <i>several</i> examples is the value part of the tuple in your API. You've pulled out the key, and forgotten to include anything in the actual groups.  I have a hunch that if your API were used, this would be a common pitfall.</div><div><br></div><div>I think this argues against your API and for Michael's that simply deals with "sequences of groupable things."  That's much more like what one deals with in SQL, and is familiar that way.  If the things grouped are compound object such as dictionaries, objects with common attributes, named tuples, etc. then the list of things in a group usually *does not* want the grouping attribute removed.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><font face="monospace, monospace"></font></div><div class="gmail_quote"><font face="monospace, monospace">grouping(((len(word), word) for word in words))<div class="gmail_quote">grouping((name[0], name) for name in names))<br></div><div class="gmail_quote">grouping((contact.city, contact) for contact in contacts) <br></div></font></div></div></div></blockquote><div><br></div><div>Good so far, but a lot of redundancy in always spelling tuple of `(derived-key, object)`.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><font face="monospace, monospace"><div class="gmail_quote"></div><div class="gmail_quote">grouping((employee['department'] for employee in employees)<br></div><div class="gmail_quote">grouping((<font face="monospace, monospace">os.path.splitext(filepath)[1]</font> for filepath in os.listdir('.')))<br></div><div class="gmail_quote">grouping((<font face="monospace, monospace">'debit' if v > 0 else 'credit' for v in </font>transactions))<br></div></font></div></div></div></blockquote><div><br></div><div>And here you forget about the object itself 3 times in a row (or also forget some derived "value" that you might want in your other comments).</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><font face="monospace, monospace"><div class="gmail_quote"></div><div class="gmail_quote">grouping(((v, k) for v, k in d.items()))<br></div></font></div></div></div></blockquote><div><br></div><div>This is nice, and spelled correctly.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><font face="monospace, monospace"><div class="gmail_quote"></div></font></div><div class="gmail_quote"><div>So that was an interesting exercise -- many of those are a bit clearer (or more compact) with the key function. But I also notice a pattern -- all those examples fit very well into the key function pattern:<br></div></div></div></div></blockquote><div><br></div><div>Yep.</div><div><br></div><div>I also think that the row-style "list of data" where you want to discard the key from the values is nicely spelled (in the PEP) as:</div><div><br></div><div><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:16px;word-wrap:normal;padding:16px;overflow:auto;line-height:1.45;background-color:rgb(246,248,250);border-radius:3px;color:rgb(36,41,46);text-decoration-style:initial;text-decoration-color:initial">INDEX = 0
grouping(sequence, key=lambda row: row.pop(INDEX))</pre></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>groups = {}<br>for item in iterable:<br>    groups.setdefault(key(item), []).append(item)<br></div></div></div></div></blockquote><div><br></div><div>I agree this seems better as an implementation.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>I still prefer the class idea over a utility function, because:<br></div><div>* with a class, you can ad stuff to the grouping later:<br></div><div><br></div><div><span style="font-family:monospace,monospace">a_grouping['key'] = value<br></span><br></div><div>or maybe <span style="font-family:monospace,monospace">a_grouping.add(item)</span><br>* with a class, you can add utility methods -- I kinda liked that in your original PEP.<br></div></div></div></div></blockquote><div><br></div><div>I agree still (after all, I proposed it to Michael).  But this seems minor, and Guido seems not to like `collections` that much (or at least he commented on not using Counter ... which I personally love to use and to teach).</div><div><br></div><div>That said, a 'grouping()' function seems fine to me also... with a couple utility functions (that need not be builtin, or even standard library necessarily) in place of methods.  A lot of what methods would do can easily be done using comprehensions as well, some examples are shown in the PEP.</div><div><br></div></div><div><br></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">Keeping medicines from the bloodstreams of the sick; food <br>from the bellies of the hungry; books from the hands of the <br>uneducated; technology from the underdeveloped; and putting <br>advocates of freedom in prisons.  Intellectual property is<br>to the 21st century what the slave trade was to the 16th.<br></div></div>