Cedric H.
Cedric H.

Reputation: 8298

Javascript equivalent of Python's 'yield from'

I have a data structure which is essentially a mixture of nested lists/dictionaries:

class System:
    def __init__(self, name, subsystems, uri):
        self.name = name
        self.subsystems = subsystems
        self.uri = uri

A = System("A", [], "http://A")
B1 = System("B1", [], "http://B/B1")
B21 = System("B12", [], "http://B/B2/B21")
B22 = System("B22", [], "http://B/B2/B22")
B2 = System("B2", [B21, B22], "http://B/B2")
B = System("B", [B1, B2], "http://B")
C1 = System("C1", [], "http://C/C1")
C = System("C", [C1], "http://C")
S = System("S", [A, B, C], None)

In Python I wrote the following recursive generator:

def find_subsystem(system, name):
    if system.name == name:
        yield system.uri
    for sub in system.subsystems:
        yield from find_subsystem(sub, name)

allowing me to do "queries" like

next(find_subsystem(S, "B22"))
#=> 'http://B/B2/B21'

or

list(find_subsystem(S, "B22"))
#=> ['http://B/B2/B21', 'http://B/B2/B22']

I am wondering how I could best write an equivalent in JavaScript: I know I could do something with yield as well however I think that the Python code is quite clean thanks to yield from. Is there an equivalent in JavaScript or a common idiom?

(I could I guess use something from underscore.js but I'd like to do it "manually" as an exercise)

Upvotes: 5

Views: 1015

Answers (1)

Cedric H.
Cedric H.

Reputation: 8298

Following @vaultah comment I obtained the following solution, using yield*:

function System(name, subsystems, uri) {
    this.name = name;
    this.subsystems = subsystems;
    this.uri = uri;
}
var A = new System("A", [], "http://A");
var B1 = new System("B1", [], "http://B/B1");
var B21 = new System("B21", [], "http://B/B2/B21");
var B22 = new System("B22", [], "http://B/B2/B22");
var B2 = new System("B2", [B21, B22], "http://B/B2");
var B = new System("B", [B1, B2], "http://B");
var C1 = new System("C1", [], "http://C/C1");
var C = new System("C", [C1], "http://C/");
var S = new System("S", [A, B, C], "");

function* find_subsystem(system, name) {
    if(system.name == name) {
        yield system.uri;
    }
    for (var i = 0; i < system.subsystems.length; i++) {
        yield* find_subsystem(system.subsystems[i], name);
    }
}

console.log(find_subsystem(S, "B22").next().value);

Upvotes: 2

Related Questions