ComfyUI Node

_.map

The one underscore node you'll actually want — map every element through a transform.

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

If you only grab one node from the ovum/underscore family in sfinktah/comfy-ovum, make it _.map. It applies a transformation to every element of a list (or every value of a dict) and collects the results into a new list. This is the workhorse - the thing that turns a list of dicts into a list of names, or a list of numbers into a list of strings, without a pile of per-element plumbing.

What it is

A graph wrapper around map in underscore3, a Python port of Underscore.js. The iteratee - the function doing the transforming - is invoked with three arguments: the value, its index (or key), and the whole list. And critically, the iteratee is normalized through _.iteratee, which means you don't have to hand it a real function every time.

Inputs that matter

Three, and the first two are the ones you'll set:

  • list_or_dict (type *) - the collection to map over.
  • iteratee (type *, force-input) - an ANY socket for the transformation. Accepts a function, a key string (plucks that field), or an object shorthand (matches properties).
  • iteratee_json (STRING, multiline) - JSON or a key selector, used when the iteratee socket isn't connected. This is your durable, save-friendly path.

Output is properly typed LIST. Feed a _.CHAIN and you get a chain back for continued chaining, resolved with _.value.

The two ways to drive it

The key-selector shorthand is the everyday win. Feed it a list of dicts and set iteratee_json to "name", and you get a list of the name values. That's the "pluck" pattern, and it's the fastest way to extract a column out of structured data. For real logic, wire a function into the iteratee socket - the pack even ships _.iteratee to build one from shorthands, and the README mentions an experimental feature where you supply an iteratee node class and it builds a tiny per-item subgraph that runs and collects its output. That last part is genuinely experimental territory; treat it as a playground, not a pillar.

The save/reload caveat

Functions are live Python objects and don't survive a workflow save/reload as JSON. If your map depends on a function in the iteratee socket, reloading the workflow will leave it empty - rebuild it in the live session. The key-selector form (iteratee_json) survives fine because it's text. If you're building a workflow you'll share or reopen later, prefer the JSON/key path.

Installing comfy-ovum

ComfyUI Manager: search for comfy-ovum, install, restart. Or by hand:

cd ComfyUI/custom_nodes
git clone https://github.com/sfinktah/comfy-ovum
pip install -r comfy-ovum/requirements.txt

Restart and you're done. No model downloads, no CUDA - pure-Python utilities. The family is officially "work in progress," and _.map is where the polish shows most - but the key-selector path is solid enough to use for real work.

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
LISTLIST