LINUX.ORG.RU

История изменений

Исправление Nervous, (текущая версия) :

Можно слегка обобщить это всё*:

def identity (x):
    return x

def partial (f, *args):
    return lambda *more: f(*args, *more)

def walk (inner, outer, tree):
    if isinstance(tree, dict):
        return dict(map(lambda entry: [inner(entry[0]), inner(entry[1])], tree.items()))
    elif isinstance(tree, list):
        return outer(list(map(inner, tree)))
    else:
        return outer(tree)

def prewalk (f, tree):
    return walk(partial(prewalk, f), identity, f(tree))

def postwalk (f, tree):
    return walk(partial(postwalk, f), f, tree)
def foo_bar_to_baz (value):
    if isinstance(value, dict) and "foo" in value and value["foo"] == "bar":
        value["foo"] = "baz"
    return value

d = {'spam': [{'foo': 'bar'}]}

print(d)
print(prewalk(foo_bar_to_baz, d))
d = {'spam': [{'foo': 'bar'}]}
d = {'spam': [{'foo': 'baz'}]}

Можно обернуть walk/prewalk/postwalk в функцию, которая будет принимать ключ и новое значение, или вообще словарь замен — дело хозяйское. Главное, сам обход дерева теперь каждый раз заново песать не надо будет.


*содрано с https://github.com/clojure/clojure/blob/master/src/clj/clojure/walk.clj

Исправление Nervous, :

Можно слегка обобщить это всё*:

def identity (x):
    return x

def partial (f, *args):
    return lambda *more: f(*args, *more)

def walk (inner, outer, tree):
    if isinstance(tree, dict):
        return dict(map(lambda entry: [inner(entry[0]), inner(entry[1])], tree.items()))
    elif isinstance(tree, list):
        return outer(list(map(inner, tree)))
    else:
        return outer(tree)

def prewalk (f, tree):
    return walk(partial(prewalk, f), identity, f(tree))

def postwalk (f, tree):
    return walk(partial(postwalk, f), f, tree)
def foo_bar_to_baz (value):
    if isinstance(value, dict) and "foo" in value and value["foo"] == "bar":
        value["foo"] = "baz"
    return value

d = {'spam': [{'foo': 'bar'}]}

print(d)
print(prewalk(foo_bar_to_baz, d))
d = {'spam': [{'foo': 'bar'}]}
d = {'spam': [{'foo': 'baz'}]}

Можно обернуть walk/prewalk/postwalk в функцию, которая будет принимать ключ и новое значение, или вообще словарь замен — дело хозяйское. Главное, сам обход дерева теперь каждый раз заново песать не надо будет.


* содрано с https://github.com/clojure/clojure/blob/master/src/clj/clojure/walk.clj

Исходная версия Nervous, :

Можно слегка обобщить это всё*:

def identity (x):
    return x

def partial (f, *args):
    return lambda *more: f(*args, *more)

def walk (inner, outer, tree):
    if isinstance(tree, dict):
        return dict(map(lambda entry: [inner(entry[0]), inner(entry[1])], tree.items()))
    elif isinstance(tree, list):
        return outer(list(map(inner, tree)))
    else:
        return outer(tree)

def prewalk (f, tree):
    return walk(partial(prewalk, f), identity, f(tree))

def postwalk (f, tree):
    return walk(partial(postwalk, f), f, tree)
def foo_bar_to_baz (value):
    if isinstance(value, dict) and "foo" in value and value["foo"] == "bar":
        value["foo"] = "baz"
    return value

d = {'spam': [{'foo': 'bar'}]}

print(prewalk(foo_bar_to_baz, d))
d = {'spam': [{'foo': 'bar'}]}
d = {'spam': [{'foo': 'baz'}]}

Можно обернуть walk/prewalk/postwalk в функцию, которая будет принимать ключ и новое значение, или вообще словарь замен — дело хозяйское. Главное, сам обход дерева теперь каждый раз заново песать не надо будет.


* содрано с https://github.com/clojure/clojure/blob/master/src/clj/clojure/walk.clj