Nodes/comfy-ovum/_.indexBy
ComfyUI Node

_.indexBy

Turn a list of records into a dict you can look up by key

By sfinktah·Created about a year ago·Updated 10 months ago· 7
_.indexBy
  • list_or_dict
  • iteratee
  • DICT
iteratee_json

_.indexBy takes a list of things and builds a dictionary keyed by something you choose. Think: "I have a list of image records, now let me look them up by filename without scanning the list." That's the whole pitch, and it's genuinely the most useful of the pack's dictionary-builders because the result is a lookup structure you can index into downstream.

How it works

It's Underscore.js's _.indexBy, which is _.groupBy's sibling for when you know your keys are unique. Given a collection and an iteratee, it runs each element through the iteratee to get a key, then stores that element under the key:

def indexBy(self, iteratee=None):
    if iteratee is None:
        iteratee = lambda *args: args[0]
    def by(result, key, value):
        result[key] = value
    res = self._group(self.obj, iteratee, by)
    return self._wrap(res)

If you give it no iteratee, it keys by the elements themselves (each element becomes its own key). Give it a property name and it keys by that property. Give it a function and it keys by whatever the function returns.

The inputs that matter

  • list_or_dict - the primary input (*). A list of records is the natural fit; it also accepts a _.CHAIN to continue chaining.
  • iteratee - an * input for a function, key string, or object shorthand that picks the key. Leave unconnected to fall back to the JSON editor below.
  • iteratee_json - a multiline STRING. This is the one you'll actually type into. The tooltip says it's "JSON or key selector," used when iteratee isn't connected. For the common case - "index by this property" - you just type the property name as a plain string, like filename or seed.

Output is a single DICT. Wire it into anything that takes a dictionary - the pack's New Multi-type Dictionary-style consumers, a _.get/_.pluck node, or a formatter that indexes {arg0[key]}.

Where you'd actually use it

The recipe that clicks: upstream you have a list of workflow records, image paths, or metadata dicts (say from a JSON loader or a list-builder). Feed it to _.indexBy with filename as the key selector, and you get a dict where filename → record. Now instead of filtering a list, you do a direct key lookup - O(1) instead of scanning. It also pairs with _.include or _.invert for reverse lookups.

One trap: _.indexBy assumes unique keys. If two elements produce the same key, the last one wins silently. That's why it's "for when you know your keys are unique" - use _.groupBy if you don't.

Installing

Ships in comfy-ovum (MIT). ComfyUI Manager → search comfy-ovum → install → restart, or clone:

cd ComfyUI/custom_nodes
git clone https://github.com/sfinktah/comfy-ovum

The underscore nodes run on the underscore3 port bundled in the repo - no extra install. The pack as a whole pulls pymediainfo, tomli-w, requests, braceexpand, pillow, numpy, markdown-it-py, aiohttp from its requirements.

Gotchas

The whole underscore family is author-labeled WIP ("an absolute disaster to use in production" is the README's own phrasing), so treat _.indexBy as an experiment, not a dependency. The iteratee story is also the fiddliest part of these nodes - functions are hard to express in a GUI, which is why you'll mostly use plain-string key selectors. Keep it to key strings and it behaves.

Categoryovum/underscore

Inputs (3)

NameTypeDefaultDescription
list_or_dictopt*Primary input object (expected collection). You can still pass any JSON-serializable value. Also accepts _.CHAIN to continue chaining.
iterateeopt*iteratee: ANY input to override widget. Accepts function, key string, or object shorthand.
iteratee_jsonoptSTRINGiteratee_json: JSON or key selector. Used when 'iteratee' input is not connected.

Outputs (1)

NameTypeDescription
DICTDICT