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

我可以在不创建另一个包装函数的情况下从内部对生成器函数进行排序,或者在外部对其进行排序吗?

如何解决我可以在不创建另一个包装函数的情况下从内部对生成器函数进行排序,或者在外部对其进行排序吗?

我有一个很好的 os.walk() 包装器,可以将深入发现的文件和目录映射到 Path 的子类:

类查找:

@staticmethod
def deep(path: Union[str,Path,'WalkPath'],sort_key=lambda p: str(p).lower()) -> ['WalkPath']:
    
    if Path(path).is_file(): 
        return [WalkPath(path)]
    
    for root,dirs,files in os.walk(WalkPath(path)):
        
        dirs = sorted([WalkPath(root).joinpath(d) for d in dirs],key=sort_key)
        files = sorted([WalkPath(root).joinpath(f) for f in files],key=sort_key)
        
        yield WalkPath(root,dirs=dirs,files=files)
        yield from files

这很有效 - 我可以对结果进行迭代,并对其中任何一个结果进行检查,检查其中包含的文件或目录。

不幸的是,返回的结果相当未排序。我知道我可以做到这一点:

paths = sorted(Find.deep(root),key=lambda p: str(p).lower())

事后,或者我可以创建一个包装函数

@staticmethod      
def sorted_deep(path):
    yield from sorted(Find.deep(root),key=lambda p: str(p).lower())

但我想知道是否有办法直接在主函数中处理排序?我尝试研究是否可以重新处理它以适合 lambda 表达式,但无法使其与分配目录和文件一起工作。

为了完整起见,这里是 WalkPath 对象:

#!/usr/bin/env python
import os
import pathlib
from pathlib import Path
from typing import Union

class WalkPath(Path):
    
    _flavour = type(Path())._flavour
    
    def __init__(self,*args,dirs: []=[],files: []=[]):
        """Initialize WalkPath object.

        Args:
            dirs (list):    Dirs provided by os.walk(),defauls to []
            files (list):   Files provided by os.walk(),defaults to []
        """
        
        super().__init__()
        
        self.dirs: [WalkPath] = list(map(WalkPath,dirs))
        self.files: [WalkPath] = list(map(WalkPath,files))
    
    def joinpath(self,path) -> 'WalkPath':
        joined = WalkPath(super().joinpath(path))
        self.__dict__ = joined.__dict__.copy()
        return joined
    
    @property
    def is_terminus(self) -> bool:
        return self.is_file() or not self.dirs
    
    @property
    def dirs_abs(self) -> ['WalkPath']:
        return [self.joinpath(d) for d in self.dirs]
    
    @property
    def files_abs(self) -> ['WalkPath']:
        return [self.joinpath(f) for f in self.files]

解决方法

排序对象的概念涉及比较其元素以确定哪些元素大于其他元素。生成器本质上一次只生成一个元素。如果您想查看按特定顺序生成的元素,理想情况下应该编写生成器的算法以生成您真正想要的顺序。否则,您必须将其整理成一个数据结构,然后对其进行排序(显然不理想,因为它失去了生成器的好处)。

就您编写的特定生成器而言,我的建议是考虑它产生“相当未排序”结果的方式 - 您已经在其中排序了一些循环,所以我希望它有一些一种秩序。准确调查您获得该订单的方式,并确定它与您希望看到的订单有何不同,然后根据需要进行调整。

就强制生成器的顺序与其算法生成的顺序不同的一般问题而言,不,如果不存储整个结果,然后将生成的元素相互比较,即排序,就无法做到这一点。

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