jz String Picker
One line out of many, on a seed you control
- text
- picked_index
- count
Every workflow eventually needs "one of these, please" - a random prompt from a bank of styles, a random negative template, a random watermark text. ComfyUI has a dozen nodes for that, and they mostly fall into one of two traps: random picks you can't reproduce, or index picks you have to babysit. jz String Picker splits the difference. You give it a list of strings, and it picks one either randomly from a seed you control, or deterministically by an index that wraps around the list.
It's the sibling of jz Choice in the jz/util menu, and the two are easy to mix up. Choice asks "which named option did you want?" and validates the answer. String Picker asks "give me one" - you pick the strategy (random or index), not the value. If you want to sweep through every entry in order on successive runs, this is the node; if you want to hard-select a named entry that must survive list edits, use Choice.
How it works
items is a multiline STRING, one entry per line (the separator dropdown lets you switch to comma, semicolon, or pipe). Blank lines are stripped and an empty list raises, so a typo'd list fails instead of silently picking from nothing.
The mode widget is where the real behavior lives:
- random - picks using a seeded RNG, so the same
seedalways gives the same pick. The seed widget has acontrol_after_generatecontrol like a KSampler's; set it to "randomize" and the pick re-rolls on every queue, or lock it for reproducibility. This is the same control-after-generate mechanism that trips people up on sampler seeds - the number shown is what runs next, so if you find a good pick, flip the control to "fixed" before you change anything else. - index - returns
items[index % count]. Because it wraps around, you can feed it an incrementing counter and step through the whole list one run at a time, forever, without ever going out of bounds. That's the sneaky-useful mode for batch sweeps.
The outputs
You get three, and two of them matter more than people expect:
- text - the picked string, ready to wire into a prompt or filename prefix.
- picked_index - which position was picked. Feed this to an "get item at index" node downstream and the rest of the graph can stay in sync with the pick.
- count - how many entries the list had. Handy for math like "run exactly once per entry" without hardcoding the list length.
Installing it
Same pack, same one-liner:
cd ComfyUI/custom_nodes
git clone https://github.com/j-zhang19/comfyui-jz
Restart ComfyUI (or install via Manager by searching "comfyui-jz"), and it appears under jz/util. Dependencies are just requests, pillow, and numpy - nothing heavy, no models.
Common issues
The usual beginner snag is expecting a random pick to stay the same after you re-run, then discovering the seed widget was set to randomize. Either is fine - just know which you're in. Second gotcha: entries are whitespace-stripped, so don't rely on leading/trailing spaces to distinguish two options; the node will silently collapse them into the same entry. And remember the empty-list raise: if the node starts erroring, check that your list actually parsed (wrong separator is the classic culprit).
It's a small personal-pack utility with no community lore to speak of - the author's README is the only documentation - but for seeded random picks and wrap-around index sweeps, it's genuinely the cleanest version of this pattern I've used.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| items | STRING | one entry per line (or per separator) | |
| mode | COMBO | random | 2 options: random, index |
| seed | INT | 00–2147483647 | random mode: same seed = same pick; set the control to 'randomize' to re-roll on every queue |
| index | INT | 00–2147483647 | index mode: wraps around the list |
| separatoropt | COMBO | newline | 4 options: newline, comma, semicolon, pipe |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |
| picked_index | INT | — |
| count | INT | — |