Python中的映射和列表理解

Python中的映射和列表理解,python,dictionary,filter,list-comprehension,reduce,Python,Dictionary,Filter,List Comprehension,Reduce,因此,我对列表理解和映射/过滤/减少的概念相当陌生,但我觉得这可以通过少行和少识别来实现: ip_tlsv1_counts = {} for filename in os.listdir(directory_path): if filename.endswith(LOG_FILE_EXTENSION): with open(os.path.join(directory_path, filename)) as file_handle: for li

因此,我对列表理解和映射/过滤/减少的概念相当陌生,但我觉得这可以通过少行和少识别来实现:

ip_tlsv1_counts = {}

for filename in os.listdir(directory_path):
    if filename.endswith(LOG_FILE_EXTENSION):
        with open(os.path.join(directory_path, filename)) as file_handle:
            for line_contents in file_handle:
                line_groups = re.search(LOG_LINE_REGEX, line_contents)
                if line_groups and line_groups.group(8) == "TLSv1":
                    if not line_groups.group(2) in ip_tlsv1_counts:
                        ip_tlsv1_counts[line_groups.group(2)] = 1
                    else:
                        ip_tlsv1_counts[line_groups.group(2)] += 1

return ip_tlsv1_counts

如果使用python 3.4+,则可以使用模块:


我将使用一个生成器函数迭代特定文件夹中具有特定扩展名的所有文件:

def filter_files(directory, extension):
    for filename in os.listdir(directory):
        if filename.endswith(extension):
            with open(os.path.join(directory, filename)) as file_handle:
                yield file_handle
然后,要遍历所有这些文件的所有行,只需在生成器的结果上使用
itertools.chain.from\u iterable

接下来,您可以使用
re.compile(LOG\u LINES\u REGEX)
来获得一个已编译的模式,这将提高性能,并且能够使用它的
。在
映射中搜索
方法:

log_line_re = re.compile(LOG_LINE_REGEX)
all_log_lines = itertools.chain.from_iterable(filter_files(directory_path, LOG_FILE_EXTENSION))

for line_groups in map(log_line_re.search, all_log_lines):
    if line_groups and line_groups.group(8) == "TLSv1":
        yield line_groups.group(2)
这将是一个生成器,它生成与其他条件匹配的所有
行组。组(2)
,因此要计算所有频率,您只需根据其结果构造一个
计数器

最后的代码是这样的:

def filter_files(directory, extension):
    for filename in os.listdir(directory):
        if filename.endswith(extension):
            with open(os.path.join(directory, filename)) as file_handle:
                yield file_handle

def get_part_of_log_files():
    log_line_re = re.compile(LOG_LINE_REGEX)
    all_log_lines = itertools.chain.from_iterable(filter_files(directory_path, LOG_FILE_EXTENSION))

    for line_groups in map(log_line_re.search, all_log_lines):
        if line_groups and line_groups.group(8) == "TLSv1":
            yield line_groups.group(2)

def original_function():
    return collections.Counter(get_part_of_log_files())

那么,它能做什么呢?通过使用两个函数,您可以减少缩进并提高清晰度。我怀疑理解是你在这里的可取之处。你可以使用
计数器来代替
dict来计算
ip\u tlsv1\u计数
,并用
ip\u tlsv1\u计数来代替你的内部
if-else
+=1
并且如果f.endswith(log\u文件扩展名),您可以通过迭代
log\u文件=(f代表os.listdir(目录路径)中的f)轻松删除缩进块
然后迭代:
对于日志文件中的文件:
@Coldspeed这使用一个正则表达式来匹配文件中的日志条目,并统计具有字段“TLSv1”的IP地址的出现次数我喜欢它,因为它分解了功能,看起来可以重用,尽管它的行数和缩进与我想知道的大致相同-谢谢你的回复!这很性感,但根据我的经验,python 3.4+是一个苛刻的要求:)谢谢你的回复-这绝对是更性感的方式
def filter_files(directory, extension):
    for filename in os.listdir(directory):
        if filename.endswith(extension):
            with open(os.path.join(directory, filename)) as file_handle:
                yield file_handle

def get_part_of_log_files():
    log_line_re = re.compile(LOG_LINE_REGEX)
    all_log_lines = itertools.chain.from_iterable(filter_files(directory_path, LOG_FILE_EXTENSION))

    for line_groups in map(log_line_re.search, all_log_lines):
        if line_groups and line_groups.group(8) == "TLSv1":
            yield line_groups.group(2)

def original_function():
    return collections.Counter(get_part_of_log_files())