问题描述
我编写了以下代码来反转图形的边缘,表示为adjacency list $today_start = Carbon::Now()->format('Y-m-d 00:00:00');
$today_end = Carbon::Now()->format('Y-m-d 23:59:59');
$start_activity = MarketingActivity::whereBetween('created_at',[$today_start,$today_end])
->orderBy('id','ASC')->limit(1)->get();
。
Mapping
示例:
from typing import Mapping,Any,Sized
from collections import defaultdict
def edge_reversed_graph(g: Mapping[Any,Sized]):
d = defaultdict(set)
for src,dst_nodes in g.items():
if len(dst_nodes):
for dst in dst_nodes:
d[dst].add(src)
elif src not in d:
d[src] = set()
return d
我希望能够仅要求图形为>>> graph = dict(a='c',b='cd',c='abd',e='')
>>> assert edge_reversed_graph(graph) == {'c': {'a','b'},'d': {'c','a': {'c'},'b': {'c'},'e': set()}
,即邻接“列表”不必一定要有长度。使用标志变量可以实现此目的,但是我正在寻找一种更优雅,更有效的解决方案,否则对我来说,使函数与更大的对象一起使用将不值得。
解决方法
检查出站容器/可迭代边缘是否为空是一个红色鲱鱼:必须始终确保每个节点都存在。
- 如果有进入的边缘,则可能之前已添加。 即使节点没有输出边缘,也可能不会被覆盖。
- 如果有传出但没有传入的边,则仍必须添加。 该节点必须存在,而与进入的边缘无关。
这消除了检查是否存在向外边缘的需要:始终添加src
节点,如果它不存在。始终迭代所有传出的边,其中可能没有一个。
from typing import Mapping,TypeVar,Iterable,Set
from collections import defaultdict
T = TypeVar('T')
def edge_reversed_graph(g: Mapping[T,Iterable[T]]) -> Mapping[T,Set[T]]:
d = defaultdict(set)
for src,dst_nodes in g.items():
d.setdefault(src,set()) # add node if not present
for dst in dst_nodes: # empty iterable does nothing
d[dst].add(src)
return d
,
类似于我对标志的假设(在循环内将bool
变量设置为True
),但效率更高:
def edge_reversed_graph(g: Mapping[Any,Iterable]):
d = defaultdict(set)
none = object()
for src,dst_nodes in g.items():
dst = none
for dst in dst_nodes:
d[dst].add(src)
if dst is none:
d[src] = set()
return d