【问题标题】:Merge the first words in a list of word-pairs, depending on the second words in those pairs合并单词对列表中的第一个单词,具体取决于这些单词对中的第二个单词
【发布时间】:2017-01-10 22:40:42
【问题描述】:

我有一个程序 (NLTK-NER),它为我提供了这个列表:

[
    ('Barak', 'PERSON'),
    ('Obama', 'PERSON'),
    ('is', 'O'),
    ('the', 'O'),
    ('president', 'O'),
    ('of', 'O'),
    ('United', 'LOCATION'),
    ('States', 'LOCATION'),
    ('of', 'LOCATION'),
    ('America', 'LOCATION')
]

如您所见,“Barak”和“Obama”是“PERSON”类型的词,我想将它们(以及“LOCATION”类型的词)合并在一起,如下所示:

['Barak Obama','is','the','president', 'of','United States of America']

我该如何解决这个问题?

【问题讨论】:

    标签: python list python-3.x tuples grouping


    【解决方案1】:

    本质上,我们在这里要做的是将classified_text 的一些项目组合在一起......所以itertools.groupby() 可以提供帮助是理所当然的。首先,我们需要一个关键函数,将带有标签'PERSON''LOCATION' 的项目视为相似,而将所有其他项目视为不同。

    这有点复杂,因为我们需要一种方法来区分具有相同标签的相邻项目('PERSON''LOCATION' 除外),例如('is', 'O'), ('the', 'O') 等。我们可以使用enumerate()

    >>> list(enumerate(classified_text))
    [..., (2, ('is', 'O')), (3, ('the', 'O')), (4, ('president', 'O')), ...]
    

    现在我们知道要向groupby() 提供什么作为输入,我们可以编写我们的关键函数:

    def person_or_location(item):
        index, (word, tag) = item
        if tag in {'PERSON', 'LOCATION'}:
            return tag
        else:
            return index
    

    请注意,赋值中index, (word, tag) 的结构与我们枚举列表中每个项目的结构相匹配。

    一旦我们得到它,我们就可以编写另一个函数来进行实际的合并:

    from itertools import groupby
    
    def merge(tagged_text):
        enumerated_text = enumerate(tagged_text)
        grouped_text = groupby(enumerated_text, person_or_location)
        return [
            ' '.join(word for index, (word, tag) in group)
            for key, group in grouped_text
        ]
    

    它在行动:

    >>> merge(classified_text)
    ['Barak Obama', 'is', 'the', 'president', 'of', 'United States of America']
    

    【讨论】:

      【解决方案2】:

      这是我想到的第一件事,很确定它可以优化,但这是一个好的开始。

          classified_text = [('Barak', 'PERSON'), ('Obama', 'PERSON'), ('is', 'O'), ('the', 'O'), ('president', 'O'), ('of', 'O'), ('United', 'LOCATION'), ('States', 'LOCATION'), ('of', 'LOCATION'), ('America', 'LOCATION')]
      
          # Reverse the list so it pops the first element
          classified_text.reverse()
          # Create an aux list to store the result and add the first item
          new_text = [classified_text.pop(), ]
          # Iterate over the text
          while classified_text:
              old_word = new_text[-1]
              new_word = classified_text.pop()
      
              # If previous word has same type, merge. 
              # Avoid merging 'O' types
              if old_word[1] == new_word[1] and new_word[1] != 'O':
                  new_text[-1] = (
                      ' '.join((old_word[0], new_word[0])),
                      new_word[1],
                  )
      
              # If not just add the tuple
              else:
                  new_text.append(new_word)
      
          # Remove the types from the list and you have your result
          new_text = [x[0] for x in new_text]
      

      【讨论】:

        猜你喜欢
        • 2015-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-26
        • 1970-01-01
        • 1970-01-01
        • 2014-10-24
        • 1970-01-01
        相关资源
        最近更新 更多