【问题标题】:Comparing like words between two dictionaries比较两个字典之间的相似词
【发布时间】:2017-01-18 18:18:25
【问题描述】:

我正在使用 python 3.x,

我有 2 部字典(都很大,但会在这里替代)。字典的值包含多个单词:

dict_a = {'key1': 'Large left panel', 'key2': 'Orange bear rug', 'key3': 'Luxo jr. lamp'}
dict_a

{'key1': 'Large left panel',
 'key2': 'Orange bear rug',
 'key3': 'Luxo jr. lamp'}

dict_b = {'keyX': 'titanium panel', 'keyY': 'orange Ball and chain', 'keyZ': 'large bear musket'}
dict_b

{'keyX': 'titanium panel',
 'keyY': 'orange Ball and chain',
 'keyZ': 'large bear musket'}

我正在寻找一种方法来比较 dict_a 的值中包含的单个单词与 dict_b 的值中包含的单词,并返回包含该单词的字典或数据框,以及来自dict_a 和 dict_b 关联:

我想要的输出(未以任何特定方式格式化):

  • 熊:key2(来自dict_a),keyZ(来自dict_b)
  • Luxo: key3
  • 橙色:key2(来自 dict_a),keyY(来自 dict_b)

我的代码可用于在单个字典中查找特定单词,但这还不够我需要在这里完成的工作:

def search(myDict, lookup):
    aDict = {}
    for key, value in myDict.items():
        for v in value:
            if lookup in v:
               aDict[key] = value
    return aDict
    print (key, value)

【问题讨论】:

    标签: python-3.x dictionary


    【解决方案1】:
    dicts = {'a': {'key1': 'Large left panel', 'key2': 'Orange bear rug', 
                   'key3': 'Luxo jr. lamp'},
             'b': {'keyX': 'titanium panel', 'keyY': 'orange Ball and chain', 
                   'keyZ': 'large bear musket'} }
    from collections import defaultdict
    index = defaultdict(list)
    for dname, d in dicts.items():
        for key, words in d.items():
            for word in words.lower().split(): # lower() to make Orange/orange match
                index[word].append((dname, key))
    

    index 现在包含:

    {'and'     : [('b', 'keyY')],
     'ball'    : [('b', 'keyY')],
     'bear'    : [('a', 'key2'), ('b', 'keyZ')],
     'chain'   : [('b', 'keyY')],
     'jr.'     : [('a', 'key3')],
     'lamp'    : [('a', 'key3')],
     'large'   : [('a', 'key1'), ('b', 'keyZ')],
     'left'    : [('a', 'key1')],
     'luxo'    : [('a', 'key3')],
     'musket'  : [('b', 'keyZ')],
     'orange'  : [('a', 'key2'), ('b', 'keyY')],
     'panel'   : [('a', 'key1'), ('b', 'keyX')],
     'rug'     : [('a', 'key2')],
     'titanium': [('b', 'keyX')] }
    

    更新到 cmets

    由于您的实际字典是从字符串到列表(而不是字符串到字符串)的映射,请将循环更改为

    for dname, d in dicts.items():
        for key, wordlist in d.items():    # changed "words" to "wordlist"
            for words in wordlist:         # added extra loop to iterate over wordlist
                for word in words.split(): # removed .lower() since text is always uppercase
                    index[word].append((dname, key))
    

    由于您的列表只有一项您可以做的事情

    for dname, d in dicts.items():
        for key, wordlist in d.items(): 
            for word in wordlist[0].split(): # assumes single item list
                index[word].append((dname, key))
    

    如果您有不想添加到索引中的单词,您可以跳过将它们添加到index:

    words_to_skip = {'-', ';', '/', 'AND', 'TO', 'UP', 'WITH', ''}
    

    然后用

    过滤掉它们
    if word in words_to_skip:
        continue 
    

    我注意到您有一些用括号括起来的单词(例如(342) 和(221))。如果你想去掉括号,请执行

    if word[0] == '(' and word[-1] == ')':
        word = word[1:-1]
    

    把这一切放在一起,我们得到了

    words_to_skip = {'-', ';', '/', 'AND', 'TO', 'UP', 'WITH', ''}
    for dname, d in dicts.items():
        for key, wordlist in d.items():
            for word in wordlist[0].split():  # assumes single item list
                if word[0] == '(' and word[-1] == ')': 
                    word = word[1:-1]         # remove outer parenthesis
                if word in words_to_skip:     # skip unwanted words
                    continue 
                index[word].append((dname, key))
    

    【讨论】:

    • 谢谢史蒂文,这正是我正在寻找的,虽然我实际使用的字典给了我一个错误:AttributeError: 'list' object has no attribute 'lower' 我的第一个 dict 看起来像:KEY1: ['AIRPLANE NUMBERS - 111'], KEY2: ['FAA TYPE CERTIFICATION'], KEY3: ['TAKEOFF AND LANDING WITH TAILWIND UP TO 15-KNOTS'],我的第二个dict 看起来像:'keyA': ['RADAR (TXT)TRANSMTT (342)'], 'keyB': ['T.E. FAIRINGS (221)'], 'keyC': ['VERTICAL FIN (313)'] 再次感谢您的帮助!另外,我是新来的,所以很抱歉格式不好。
    • @PixarJunkie:你的字典是从字符串到列表的映射,我编写了从字符串到字符串的映射代码({KEY1: ['AIRPLANE NUMBERS - 111']} vs {KEY1: 'AIRPLANE NUMBERS - 111'}。为了告诉你如何修复我有几个问题。列表中是否有不止一项(即{'KEY1': ['AIRPLANE NUMBERS - 111', 'SOMETHING ELSE']}?你的值总是大写吗?'RADAR (TXT)TRANSMTT (342).split()' 会给你字符串['RADAR', '(TXT)TRANSMTT', '(342)']。没关系还是你想要什么喜欢['RADAR', 'TXT', 'TRANSMIT', '342']?
    • Rumbaski:是的,直到出现错误,我才意识到这一点,对不起!一个列表中永远不会超过一个项目,尽管有- ; / 和其他各种符号贯穿始终。一切都是大写,没有例外。第一种情况可以正常工作,因为将(TXT) 与TRNASMTT 分开会返回一些不相关的结果。
    • @PixarJunkie:更新了我的答案。
    • @Steven Rumbalski:谢谢这个完美的作品!我对另外一件事感到好奇... :) 如果我想将word 添加到index,前提是它同时出现在dicts 中,那会是什么样子?我在index[word].append((dname, key)) 之前尝试过if word in {'a'} and word in {'b'}: ,但它返回了一个空列表。再次感谢,非常感谢您的帮助!
    【解决方案2】:

    我认为你可以很容易地做你想做的事。此代码以{word: {key: name_of_dict_the_key_is_in}}:

    格式生成输出
    def search(**dicts):
        result = {}
    
        for name, dct in dicts.items():
            for key, value in dct.items():
                for word in value.split():
                    result.setdefault(word, {})[key] = name
    
        return result
    

    您使用输入字典作为关键字参数来调用它。您为每个字典使用的关键字将是用于在输出字典中描述它的字符串,因此请使用 search(dict_a=dict_a, dict_b=dict_b) 之类的内容。

    如果您的字典可能有一些相同的键,则此代码可能无法正常工作,因为如果它们的值中包含相同的单词,这些键可能会发生冲突。你可以让外部字典包含(key, name) 元组的列表,而不是内部字典,我想。只需将分配行更改为result.setdefault(word, []).append((key, name))。不过这样搜索起来就不那么方便了。

    【讨论】:

    • 谢谢@Blckknght!我在上面使用 Stevens 解决方案时遇到了类似的错误 AttributeError: 'list' object has no attribute 'split',所以我认为我需要为我的特定词典做一些额外的格式化。
    • 啊,您传入的字典似乎将列表作为值,而不是纯字符串。如果列表中总是只有一个字符串,您可以使用value[0].split(),否则您可能需要添加一个额外的循环来遍历列表项并拆分它们中的每一个(假设您确实想按单词拆分,就像您一样隐含在问题中)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 2018-07-15
    相关资源
    最近更新 更多