<div dir="ltr"><div class="gmail_default"><div class="gmail_default"><font face="monospace, monospace">There are a few tools that can accomplish these map-reduce/transformation tasks.</font></div><div class="gmail_default"><font face="monospace, monospace">See Options A, B, C below.</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace"># Given</font></div><div class="gmail_default"><font face="monospace, monospace">    >>> import itertools as it</font></div><div class="gmail_default"><font face="monospace, monospace">    >>> import collections as ct</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace">    >>> import more_itertools as mit</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace">    >>> student_school_list = [</font></div><div class="gmail_default"><font face="monospace, monospace">    ...     ("Albert", "Prospectus"), ("Max", "Smallville"), ("Nikola", "Shockley"), ("Maire", "Excelsior"),</font></div><div class="gmail_default"><font face="monospace, monospace">    ...     ("Neils", "Smallville"), ("Ernest", "Tabbicage"), ("Michael", "Shockley"), ("Stephen", "Prospectus")</font></div><div class="gmail_default"><font face="monospace, monospace">    ... ]</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace">    >>> kfunc = lambda x: x[1]</font></div><div class="gmail_default"><font face="monospace, monospace">    >>> vfunc = lambda x: x[0]</font></div><div class="gmail_default"><font face="monospace, monospace">    >>> sorted_iterable = sorted(student_school_list, key=kfunc)</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace"># Example (see OP)</font></div><div class="gmail_default"><font face="monospace, monospace">    >>> student_by_school = ct.defaultdict(list)</font></div><div class="gmail_default"><font face="monospace, monospace">    >>> for student, school in student_school_list:</font></div><div class="gmail_default"><font face="monospace, monospace">    ...    student_by_school[school].append(student)</font></div><div class="gmail_default"><font face="monospace, monospace">    >>> student_by_school</font></div><div class="gmail_default"><font face="monospace, monospace">    defaultdict(list,</font></div><div class="gmail_default"><font face="monospace, monospace">                {'Prospectus': ['Albert', 'Stephen'],</font></div><div class="gmail_default"><font face="monospace, monospace">                 'Smallville': ['Max', 'Neils'],</font></div><div class="gmail_default"><font face="monospace, monospace">                 'Shockley': ['Nikola', 'Michael'],</font></div><div class="gmail_default"><font face="monospace, monospace">                 'Excelsior': ['Maire'],</font></div><div class="gmail_default"><font face="monospace, monospace">                 'Tabbicage': ['Ernest']})</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace">---</font></div><div class="gmail_default"><font face="monospace, monospace">    </font></div><div class="gmail_default"><font face="monospace, monospace"># Options</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace"># A: itertools.groupby</font></div><div class="gmail_default"><font face="monospace, monospace">    >>> {k: [x[0] for x in v] for k, v in it.groupby(sorted_iterable, key=kfunc)}</font></div><div class="gmail_default"><font face="monospace, monospace">    {'Excelsior': ['Maire'],</font></div><div class="gmail_default"><font face="monospace, monospace">    'Prospectus': ['Albert', 'Stephen'],</font></div><div class="gmail_default"><font face="monospace, monospace">    'Shockley': ['Nikola', 'Michael'],</font></div><div class="gmail_default"><font face="monospace, monospace">    'Smallville': ['Max', 'Neils'],</font></div><div class="gmail_default"><font face="monospace, monospace">    'Tabbicage': ['Ernest']}</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace"># B: more_itertools.groupby_transform</font></div><div class="gmail_default"><font face="monospace, monospace">    >>> {k: list(v) for k, v in mit.groupby_transform(sorted_iterable, keyfunc=kfunc, valuefunc=vfunc)}</font></div><div class="gmail_default"><font face="monospace, monospace">    {'Excelsior': ['Maire'],</font></div><div class="gmail_default"><font face="monospace, monospace">     'Prospectus': ['Albert', 'Stephen'],</font></div><div class="gmail_default"><font face="monospace, monospace">     'Shockley': ['Nikola', 'Michael'],</font></div><div class="gmail_default"><font face="monospace, monospace">     'Smallville': ['Max', 'Neils'],</font></div><div class="gmail_default"><font face="monospace, monospace">     'Tabbicage': ['Ernest']}</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace"># C: more_itertools.map_reduce</font></div><div class="gmail_default"><font face="monospace, monospace">    >>> mit.map_reduce(student_school_list, keyfunc=kfunc, valuefunc=vfunc)</font></div><div class="gmail_default"><font face="monospace, monospace">    defaultdict(None,</font></div><div class="gmail_default"><font face="monospace, monospace">                {'Prospectus': ['Albert', 'Stephen'],</font></div><div class="gmail_default"><font face="monospace, monospace">                 'Smallville': ['Max', 'Neils'],</font></div><div class="gmail_default"><font face="monospace, monospace">                 'Shockley': ['Nikola', 'Michael'],</font></div><div class="gmail_default"><font face="monospace, monospace">                 'Excelsior': ['Maire'],</font></div><div class="gmail_default"><font face="monospace, monospace">                 'Tabbicage': ['Ernest']})</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace">---</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace"># Summary</font></div><div class="gmail_default"><br></div><div class="gmail_default"><font face="monospace, monospace">- Option A: standard library, sorted iterable, some manual value transformations (via list comprehension)</font></div><div class="gmail_default"><font face="monospace, monospace">- Option B: third-party tool, sorted iterable, accepts a value transformation function</font></div><div class="gmail_default"><font face="monospace, monospace">- Option C: third-party tool, any iterable, accepts transformation function(s)</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace">I have grown to like `itertools.groupby`, but I understand it can be odd at first.</font></div><div class="gmail_default"><font face="monospace, monospace">Perhaps something like the `map_reduce` tool (or approach) may help?  It's simple,</font></div><div class="gmail_default"><font face="monospace, monospace"> does not require a sorted iterable as in A and B, and you have control over how </font></div><div class="gmail_default"><font face="monospace, monospace"> you want your keys, values and aggregated/reduced values to be (see docs for more details).</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace">    </font></div><div class="gmail_default"><font face="monospace, monospace"># Documentation</font></div><div class="gmail_default"><font face="monospace, monospace"><br></font></div><div class="gmail_default"><font face="monospace, monospace">- Option A: <a href="https://docs.python.org/3/library/itertools.html#itertools.groupby">https://docs.python.org/3/library/itertools.html#itertools.groupby</a></font></div><div class="gmail_default"><font face="monospace, monospace">- Option B: <a href="https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.groupby_transform">https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.groupby_transform</a></font></div><div class="gmail_default"><font face="monospace, monospace">- Option C: <a href="https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.map_reduce">https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.map_reduce</a></font></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jun 28, 2018 at 8:37 PM, Chris Barker - NOAA Federal via Python-ideas <span dir="ltr"><<a href="mailto:python-ideas@python.org" target="_blank">python-ideas@python.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">> On Jun 28, 2018, at 5:30 PM, Chris Barker - NOAA Federal <<a href="mailto:chris.barker@noaa.gov">chris.barker@noaa.gov</a>> wrote:<br>
><br>
> So maybe a solution is an accumulator special case of defaultdict — it uses a list be default and appends by default.<br>
><br>
> Almost like counter...<br>
<br>
</span>Which, of course, is pretty much what your proposal is.<br>
<br>
Which makes me think — a new classmethod on the builtin dict is a<br>
pretty heavy lift compared to a new type of dict in the collections<br>
module.<br>
<div class="HOEnZb"><div class="h5"><br>
-CHB<br>
______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br>
</div></div></blockquote></div><br></div>