我在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
我无法找到有关如何搜索字典中某个字段的详细信息,如果找到匹配项则更新另一个字段。 我哪里错了?
答案 0 :(得分:2)
您无法搜索字典的值:它的键被索引,并且根本没有索引值(实际上,它们甚至可能不可编辑)。
您有两个选择:
重新设计您的问题,以便电话号码实际上是关键:
{
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>将您的数据结构保存为列表,并通过它直接搜索匹配项:
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
这样可以很好地工作(让几个人拥有相同的电话号码。好的,坏的?由你来决定),但是当你走完整个目录时,它显然非常有效每次。如果你有一个已知的小数据集,这可能是最好的解决方案。
(在我看来,最好的选择)两者的某种组合。您通常可以将数据存储在一个对象中,并将多个索引作为词典:
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