Python 如何在固定的距离内获取一个单词周围的所有单词

Python 如何在固定的距离内获取一个单词周围的所有单词,python,python-3.x,text-processing,Python,Python 3.x,Text Processing,我有可变大小的文本(1k-100k个字符)。我想在固定的距离内获取给定单词周围的所有单词。给定的单词是从正则表达式中获得的,因此我有单词的开头和结尾 例如: PROXIMITY_LENGTH = 10 # the fixed proximity my_text = 'some random words 1123 word1 word123 a' start, stop = re.search(r'\b1123\b', my_text).span() print(f'start = {star

我有可变大小的文本(1k-100k个字符)。我想在固定的距离内获取给定单词周围的所有单词。给定的单词是从正则表达式中获得的,因此我有单词的开头和结尾

例如:

PROXIMITY_LENGTH = 10  # the fixed proximity
my_text = 'some random words 1123 word1 word123 a'
start, stop = re.search(r'\b1123\b', my_text).span()

print(f'start = {start}, stop = {stop}')
print(my_text[start - PROXIMITY_LENGTH: start]) 
print(my_text[stop: stop + PROXIMITY_LENGTH])

left_limit = my_text[:start - PROXIMITY_LENGTH].rfind(' ') + 1
right_limit = stop + PROXIMITY_LENGTH + my_text[stop + PROXIMITY_LENGTH:].find(' ') 

print('\n')
print(my_text[left_limit: start]) 
print(my_text[stop: right_limit])
输出:

start = 18, stop = 22
dom words 
 word1 wor


random words 
 word1 word123
'\twords 123 123 - 123 some '
问题已经到了极限,固定的接近度可以减少最后一个字(从右/左极限)。 在上面的示例中,我试图提供一个解决方案,但如果我在单词之间使用制表符或换行符作为定界符,我的解决方案将失败,例如:

对于
my_text='some\trandom words 1123 word1 word123 a'
我的解决方案出现在左侧:
一些随机单词
,这是错误的


感谢您的帮助!谢谢

我不看字符,而是看单词。这样,您会说,找到我的目标,并在其前后添加N个单词:

PROXIMITY_LENGTH = 2  # the fixed proximity
my_text = 'some random words 1123 word1 word123 a \t1123 this too will work'.split()

found = [x.find('1123') for x in my_text]

k = [' '.join(my_text[index-PROXIMITY_LENGTH:index+PROXIMITY_LENGTH+1]) for index, item in enumerate(found) if item == 0]


print(k)

# ['random words 1123 word1 word123', 'word123 a 1123 this too']

使用regex,我们可以用替换
found
变量


找到=[]
对于my_文本中的x:
如果重新搜索(r'\b1123\b',x):
找到。追加(0)
其他:
找到。追加(-1)

我唯一想做的就是将字符串拆分为一个列表:)

这可以通过简单地扩展正则表达式模式来完成,以包括目标匹配周围所需的字数:

L = 2 # using a proximity length of just 2 for demo
my_text = 'some random words 1123 word1 word123 a'
print(re.search(r'(\w+\s+){{0,{0}}}\b1123\b(\s+\w+){{0,{0}}}'.format(L), my_text).group())
这将产生:

random words 1123 word1 word123

如果你想根据符号(从开始/停止的距离)得到接近,并且你希望到达空洞单词,一旦接近距离结束在单词的中间。

在这种情况下,我建议搜索第一个非字母字符,它既不是字母也不是数字。 请尝试以下代码:

import re
import string

def get_left_limit(left_string, proximity, right_limit=False):
    if proximity >= len(left_string):
        return len(left_string)

    start_diff = 0
    for letter in reversed(list(left_string[:-proximity])):
        if letter not in (string.ascii_letters + string.digits):
            break
        start_diff += 1
    return proximity + start_diff

def get_right_limit(right_string, proximity):
    if proximity >= len(right_string):
        return len(right_string)

    end_diff = 0
    for letter in list(right_string[proximity:]):
        if letter not in (string.ascii_letters + string.digits):
            break
        end_diff += 1
    return proximity + end_diff


PROXIMITY_LENGTH = 10  # the fixed proximity


# example 1
print('Example: 1')
my_text = 'some random words 1123 word1 word123 a'
start, stop = re.search(r'\b1123\b', my_text).span()
print(f'start = {start}, stop = {stop}')
#
left_proximity = get_left_limit(my_text[:start], PROXIMITY_LENGTH)
right_proximity = get_right_limit(my_text[stop:], PROXIMITY_LENGTH)
print(my_text[start - left_proximity:start])
print(my_text[stop:stop + right_proximity])

# example 2
print()
print('Example: 2')
my_text = 'some\trandom words 1123 word1 word123 a'
start, stop = re.search(r'\b1123\b', my_text).span()
print(f'start = {start}, stop = {stop}')
#
left_proximity = get_left_limit(my_text[:start], PROXIMITY_LENGTH)
right_proximity = get_right_limit(my_text[stop:], PROXIMITY_LENGTH)
print(my_text[start - left_proximity:start])
print(my_text[stop:stop + right_proximity])
上述代码将产生以下结果:

Example: 1
start = 18, stop = 22
random words 
 word1 word123

Example: 2
start = 18, stop = 22
random words 
 word1 word123
  • 创建单词分隔符('\s+'的索引列表)
  • 使用找到的单词
    .span()
    在列表中查找搜索的子字符串的开始/结束位置
  • 从上面提到的位置向左和向右取所需数量的项目将在文本中给出向左和向右的“限制”
代码:

text='some random\twords 123-123其他一些随机单词。'
regex=r'\b\d((\s*\s*-\s*)\d){8}\b'
邻居=2
search_b,search_e=re.search(regex,text).span()
splitted=[(0,0)]+[m.span(0)代表re.FindItemer('\s+',text)]+[(len(text),len(text))]
左极限,右极限=无,无
对于枚举(拆分)中的ix(beg,end):
如果左极限为无且beg>=搜索:
左极限=拆分[最大值(0,ix-1-相邻)][1]
如果right\u limit为None,则搜索\u e>>
随机词123-123其他一些

所有的答案都非常有用,但我有一个简单的方法,将所有接近范围内的单词,除了那些来自限制的单词,因此如果接近限制将删除一个单词,该单词将不被考虑。这种方法更有效:

text = ' some random\twords 123 123 - 123 some other random words.' 
regex = r'\b\d((\s*|\s*-\s*)\d){8}\b'
PROXIMITY_LENGTH = 10
REGEX_NO_START_END_WORD = r'\W.+\W'

start, end = re.search(regex, text).span()

left_limit = start - PROXIMITY_LENGTH
if left_limit < 0:
    left_limit = 0

right_limit = end + PROXIMITY_LENGTH
if right_limit > len(text):
    right_limit = len(text)

text_within_proximity = text[left_limit: right_limit]
re.search(REGEX_NO_START_END_WORD, text_within_proximity, flags=re.DOTALL).group()

使用单词(按照您描述的方式)的问题是正则表达式,而不仅仅是一个单词(还包括空格和制表符),这样我就知道了文本中单词的开头和结尾。谢谢你的回答!(我投了赞成票)谢谢!在很多情况下,我们可以让regex工作。你能和你要找的正则表达式分享最难的例子吗,我会尝试解决它。好的,最难的是:my_text='一些随机词123-123一些其他随机词。'regex=r'\b\d((\s*\s*-\s*)\d){9}\b)'regex=r'\b\d((\s*\s*-\s*)\d){8}\b'谢谢你的回答!你在寻找文字,而不是文字!(upvote)right\u limit用于文本切片,因此无需减去1
'\twords 123 123 - 123 some '