微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在不依赖`len`或不消耗迭代器的情况下检查python迭代器是否为空

如何解决在不依赖`len`或不消耗迭代器的情况下检查python迭代器是否为空

我编写了以下代码来反转图形的边缘,表示为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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。