搜索Python字典并在找到的位置增加值

时间:2015-12-07 15:36:14

标签: python dictionary

我在python中有一个数据字典:

    [
    {u'PhoneOwner': u'Bob', u'Frequency': 0, u'PhoneNumber': u'123456789'},
    {u'PhoneOwner': u'Sarah', u'Frequency': 0, u'PhoneNumber': u'98765431'}
    ]

我有一个使用PhoneNumber调用的列表,我想尝试将列表与字典进行比较,并在列表中的数字出现在字典中时更新频率,最终到达:

    [
    {u'PhoneOwner': u'Bob', u'Frequency': 5, u'PhoneNumber': u'123456789'},
    {u'PhoneOwner': u'Sarah', u'Frequency': 8, u'PhoneNumber': u'98765431'}
    ]

目前我有:

      with open("CallLog.txt") as connectedNumbers:         
      for line in connectedNumbers:
      try:
              phoneNumberDictionary[PhoneNumber] += phoneNumberDictionary[Frequency]1
      except KeyError:
              phoneNumberDictionary[PhoneNumber] = phoneNumberDictionary[Frequency]1

我无法找到有关如何搜索字典中某个字段的详细信息,如果找到匹配项则更新另一个字段。 我哪里错了?

4 个答案:

答案 0 :(得分:2)

您无法搜索字典的值:它的键被索引,并且根本没有索引值(实际上,它们甚至可能不可编辑)。

您有两个选择:

  1. 重新设计您的问题,以便电话号码实际上是关键:

    {
         u'123456789': {u'PhoneOwner': u'Bob', u'Frequency': 0},
         u'98765431': {u'PhoneOwner': u'Sarah', u'Frequency': 0},
    }
    

    这非常实用,因为它可以让你立即索引你的字典:

    with open("Calllog.txt") as log:
        for line in log:
            phoneNumberDictionary[line]['Frequency'] += 1
    

    但这意味着您必须重新修改您的数据,这可能不是您想要对数据做任何其他事情最方便的事情(例如按所有者名称搜索)

    < / LI>
  2. 将您的数据结构保存为列表,并通过它直接搜索匹配项:

    with open("Calllog.txt") as log:
        for line in log:
            entries = filter(lambda entry: entry['PhoneNumber'] == line, phoneNumberDirectory)
            for entry in entries:
                entry['Frequency'] += 1
    

    这样可以很好地工作(让几个人拥有相同的电话号码。好的,坏的?由你来决定),但是当你走完整个目录时,它显然非常有效每次。如果你有一个已知的小数据集,这可能是最好的解决方案。

  3. (在我看来,最好的选择)两者的某种组合。您通常可以将数据存储在一个对象中,并将多个索引作为词典:

    class PhoneNumbers(object):
        def __init__(self, entries):
            self.frequencies = []
            self.names = {}
            self.numbers = {}
            for i, entry in enumerate(entries):
                self.frequencies.append(entry['Frequency'])
                self.names[entry['PhoneOwner']] = entry['PhoneNumber']
                self.numbers[entry['PhoneNumber']] = i
    
        def register_call(self, number):
            self.frequencies[self.numbers[number]] += 1
    
    data = PhoneNumbers(phoneNumberDictionary)
    with open("Calllog.txt") as log:
        for line in log:
            data.register_call(line)
    

    或围绕这些行的某些变化与您打算对数据进行匹配。

答案 1 :(得分:1)

我要提出建议:

将phoneNumberDict转换为字典词典。每个密钥都是一个电话号码,每个值都是dict,其余信息。这样,您每次都不需要循环遍历字典列表。

观察:

phoneNumberDictionary = { 
                         '123456789': {u'PhoneOwner': u'Bob', u'Frequency': 0},
                         '987654321': {u'PhoneOwner': u'Sarah', u'Frequency': 0}
                        }
callLogList = ['123456789', 
               '123456789', 
               '123456789', 
               '123456789', 
               '123456789', 
               '987654321', 
               '987654321', 
               '987654321', 
               '987654321', 
               '987654321', 
               '987654321', 
               '987654321', 
               '987654321',
               '000000000'
              ]

for phoneNumber in callLogList:
    if phoneNumber in phoneNumberDictionary:
        phoneNumberDictionary[phoneNumber]['Frequency'] += 1

print (phoneNumberDictionary)

无需每次都遍历电话号码列表,这将是一个更高效的脚本,尤其是随着电话号码列表的增长。

我还将for循环的try-except更改为if语句,因为这比每次不包含数字时捕获异常要快。我已经包含了一个哑铃电话号码,因此您可以看到它仍能正常运行。

希望这有帮助。

答案 2 :(得分:0)

如果改变你的数据结构还为时不晚,那么使用电话号码作为密钥,使用顶级字典从一个dicts列表变为一个dicts字典会更有效率。如果您使用的是列表,因为订单很重要,您可以使用OrderedDict

使用您当前的数据结构回答您的问题:由于您有一个词典列表,您需要做的第一件事就是找到与您要增加的电话号码对应的词典。您可以使用下面index_dict_in_list()之类的函数来执行此操作:

def index_dict_in_list(list_, key, value):
    """
    Given a list of dicts, a key, and a value, return the
    index of the dict with the matching key:value pair.
    """
    for idx, dict_ in enumerate(list_):
        if dict_[key] == value:
            return idx
    return -1

然后你可以像这样使用它:

phonebook = [
    {u'PhoneOwner': u'Bob', u'Frequency': 0, u'PhoneNumber': u'123456789'},
    {u'PhoneOwner': u'Sarah', u'Frequency': 0, u'PhoneNumber': u'98765431'}
]

page = index_dict_in_list(phonebook, 'PhoneNumber', '98765431')
phonebook[page]['Frequency'] =+ 1

答案 3 :(得分:0)

看,你有一个字典列表,你必须遍历列表并检查该行是否与该特定字典的PhoneNumber匹配。如果匹配,则将字典的Frequency增加1。

  with open("CallLog.txt") as connectedNumbers:         
  for line in connectedNumbers:
      for value in data:
          if line== value['PhoneNumber']:
              value['Frequency']+=1