【问题标题】:Python dictionary search values for keys using regular expression使用正则表达式的键的 Python 字典搜索值
【发布时间】:2012-05-29 08:56:22
【问题描述】:

我正在尝试实现在 Python 字典中搜索特定键值的值(使用正则表达式作为键)。

例子:

我有一个 Python 字典,它的值如下:

{'account_0':123445,'seller_account':454545,'seller_account_0':454676, 'seller_account_number':3433343}

我需要搜索键为“seller_account”的值?我写了一个示例程序,但想知道是否可以做得更好。主要原因是我不确定正则表达式并错过了一些东西(比如我如何为以'seller_account'开头的键设置re):

#!usr/bin/python
import re
my_dict={'account_0':123445,'seller_account':454545,'seller_account_0':454676, 'seller_account_number':3433343}

reObj = re.compile('seller_account')

for key in my_dict.keys():
        if(reObj.match(key)):
                print key, my_dict[key]

~ home> python regular.py

seller_account_number 3433343
seller_account_0 454676
seller_account 454545

【问题讨论】:

  • 如果你必须经常搜索这些键的部分,你的数据结构可能有问题。
  • 每当我遇到像 eumiro 这样的 cmets 时,我都会觉得有人在想象一个完美的整体世界,在这个世界中,OP 可以完全控制她工作的各个方面。你真的认为@Programmer 可以控制接收到的数据结构吗?除非这是一个学校项目,否则我非常怀疑。

标签: python


【解决方案1】:

如果只需要检查以"seller_account"开头的键,则不需要正则表达式,只需使用startswith()

my_dict={'account_0':123445,'seller_account':454545,'seller_account_0':454676, 'seller_account_number':3433343}

for key, value in my_dict.iteritems():   # iter on both keys and values
        if key.startswith('seller_account'):
                print key, value

或以 one_liner 方式:

result = [(key, value) for key, value in my_dict.iteritems() if key.startswith("seller_account")]

注意:对于 python 3.X 使用,将 iteritems() 替换为 items() 并且不要忘记为 print 添加 ()

【讨论】:

  • 要使result 再次成为字典,您可以使用dict() 或(在Python 2.7 中){...} 而不是列表理解[...]
  • 在 Python3 中你必须使用 items() 而不是 iteritems()
  • 但是你正在失去字典的效率,不是吗?访问不再是 O(1),因为您必须对字典元素进行 for 循环。
  • 无论如何,您都需要手动搜索每个键,因此效率对我们来说并没有多大作用
【解决方案2】:

你可以用 dpath 解决这个问题。

http://github.com/akesterson/dpath-python

dpath 允许您在键上使用 glob 语法搜索字典,并过滤值。你想要的是微不足道的:

$ easy_install dpath
>>> dpath.util.search(MY_DICT, 'seller_account*')

... 这将为您返回一个包含与该 glob 匹配的所有键的大合并字典。如果您只想要路径和值:

$ easy_install dpath
>>> for (path, value) in dpath.util.search(MY_DICT, 'seller_account*', yielded=True):
>>> ... # do something with the path and value

【讨论】:

  • 安德鲁,我会小心张贴而不透露。 你所有的答案都是关于dpath的。你显然喜欢(或部分)dpath;如果您是,我想提醒您,必须披露您的隶属关系。
  • 从github url来看,似乎Andrew是dpath的主要作者。鉴于它是 MIT 许可软件,我认为它没有任何问题。
【解决方案3】:
def search(dictionary, substr):
    result = []
    for key in dictionary:
        if substr in key:
            result.append((key, dictionary[key]))   
    return result

>>> my_dict={'account_0':123445,'seller_account':454545,'seller_account_0':454676, 'seller_account_number':3433343}
>>> search(my_dict, 'seller_account')
[('seller_account_number', 3433343), ('seller_account_0', 454676), ('seller_account', 454545)]

【讨论】:

  • 您可以通过不区分大小写来使搜索更加通用,例如将搜索词和键转换为小写:if substr.lower() in key.lower()
【解决方案4】:

您可以使用“re”和“filter”的组合。例如,如果您想在 os 模块中搜索其方法名称中包含“stat”一词的方法,您可以使用下面的代码。

import re 
import os
r = re.compile(".*stat.*")
list(filter(r.match, os.__dict__.keys()))

结果是:

['stat', 'lstat', 'fstat', 'fstatvfs', 'statvfs', 'stat_result', 'statvfs_result']

我认为原始问题中的性能问题是使用“re”模块找到键后的 key_value 搜索。如果密钥的一部分是可互换的,我们就不能使用“startswith”。所以“re”是一个不错的选择。另外,我使用过滤器来获取所有匹配键的列表并列出它们,以便我们可以使用简单的 [DICT[k] for k in LIST] 返回所有值。

【讨论】:

  • 请问您的回答与最初的关于搜索词典的问题有什么关系?
  • 我认为原始问题中的性能问题是使用“re”模块建立键后的键值搜索。如果键的一部分是可互换的,我们不能使用“startswith”所以“重新”是一个不错的选择。另外,我使用过滤器来获取所有匹配键的列表并列出它们,这样我们就可以使用简单的 [DICT[k] for k in LIST] 返回所有值。
  • @EhsanAhmadi 您应该将您的评论添加到答案中以使其更准确
【解决方案5】:

比如我如何为以“seller_account”开头的密钥设置 re

reObj = re.compile('seller_account')

应该是:

reObj = re.compile('seller_account.*')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-05
    • 2014-10-14
    • 2021-12-04
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 2013-04-14
    相关资源
    最近更新 更多