Który kod jest czytelniejszy?

46

Mam takiego śmiesznego case.

Jest sobie list comprehension, które tworzy dzienniki w zależności, czy konkretny klucz w źródle istnieje. Jeśli istnieje, to dziennik ma mieć dwa klucze, jeśli nie to jeden.

input to +/- cos takiego ->

{"cols":{"header1":{"formula":"test", "dupa":"test",...}}}

Pierwsze podejście:

from typing import Callable

dict_creator: Callable[[str, dict], dict] = lambda key, value: {"header": key} | ({"formula": value["formula"]} if "formula" in value else {})
cols = [
    dict_creator(k,v)
    for k, v in inp["cols"].items()
]
print(cols)

Jako, że klucz formula istnieje to output powinien wyglądać tak - [{'header': 'header1', 'formula': 'test'}]. Gdy by nie istniał to -> [{'header': 'header1'}]

Drugie podejście:

cols = [
    {"header": k} | ({"formula": v["formula"]} if "formula" in v else {})
    for k, v in inp["cols"].items()
]
print(cols)

Może ktoś ma jeszcze inny sposób :D

0

No jak będziemy wykonywać if key == something: to złożoność powinna wynosić O(n), a jeśli zrobimy dict[something] to nawet O(log n).

Jako, że są multi zagnieźdzenia to będzie trzeba przeszukać wszystkie, co na pewno nie jest najlepszym rozwiązaniem.

2

No wybierając pomiędzy tymi dwoma, to to drugie jest czytelniejsze kapkę dla mnie, ale nie dużo.

Trochę się zastanawiam, po co chcesz zwrócić listę dictów, z różną ilością kluczy? Trochę mogłoby się wydawać że słaby design.

Ale jeśli już się uprzesz że chcesz mieć listę słowników z różną ilością kluczy, to dla mnie najczytelniejsze jest takie coś:

def func(key:str, v: dict) -> dict:
  if "formula" in v:
    return {"header": k, "formula": v["formula"]}
  return {"header": k}
      

cols = [func(k, v) for k, v in inp["cols"].items()]
print(cols)
1

Można też tak:

[{a: b for (a, b) in [("header", k), ("formula", v.get("formula"))] if b} for (k, v) in input["cols"].items()]

Wadą (lub zaletą w zależności od use-case) jest jeśli klucz formula istnieje, ale jest falsy, to będzie otfiltrowany:

>>> input = {"cols":{"header1":{"formula":None, "dupa":"test"}}}
>>> # Od OP-a
>>> [{"header": k} | ({"formula": v["formula"]} if "formula" in v else {}) for k, v in input["cols"].items()]
[{'header': 'header1', 'formula': None}]
>>> # Moje
>>> [{a: b for (a, b) in [("header", k), ("formula", v.get("formula"))] if b} for (k, v) in input["cols"].items()]
[{'header': 'header1'}]
>>> 

Ale pewnie po prostu napisałbym zwykłą pętlę zamiast próbować być sprytnym.

2

Ja bym proponował coś takiego:

def get_formatted_dict_for_forumla(cols):
    for header, v in cols.items():
        if "formula" in v:
            yield {"header" : header, "formula": v["formula"]}
        else:
            yield {"header" : header}

        
print(list(get_formatted_dict_for_forumla(inp["cols"])))

Oczywiście nazwy zmiennych do dostosowania

1 użytkowników online, w tym zalogowanych: 0, gości: 1