首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >查找python字符串数组(numpy)条目的匹配项,作为另一个数组的子字符串搜索

查找python字符串数组(numpy)条目的匹配项,作为另一个数组的子字符串搜索
EN

Stack Overflow用户
提问于 2021-03-23 04:52:14
回答 3查看 66关注 0票数 1

我在python中有两个数组。一个包含一个字符串列表,我想使用这个列表中的每个字符串在另一个数组中进行搜索,如果这个字符串作为子字符串包含在另一个数组中。

代码语言:javascript
复制
result_list = []
array_1 = np.array(['ab', 'fo', 'ba']) # just as a veeeery easy example
array_2 = np.array(['lab', 'abc', 'zwf', 'foo', 'bar'])
for word_to_search in array_1:
  for potential_word in array_2:
    if word_to_search in potential_word:
      result_list.append(potential_word)
result_list = list(set(result_list)) # delete duplicates

# result_list = ['lab', 'abc', 'foo', 'bar']

我在基本的python列表和numpy数组中尝试过。由于性能原因,后者要好得多,但我仍然认为必须有更好的解决方案。

因为我的array_1大约有11,000,000个条目,而我的array_2大约有300,000个条目,所以我需要有一个非常高性能的方法,这不是我目前的解决方案的情况……

EN

回答 3

Stack Overflow用户

发布于 2021-03-23 04:58:05

在步骤result.append(potential_word)之后,你可以跳出for循环,这样你就不会有重复的东西,而且肯定会节省时间。此外,您还需要更改for循环的顺序,外部循环通过array_2循环,内部循环通过array_1循环。

代码语言:javascript
复制
import numpy as np
result_list = []
array_1 = np.array(['ab', 'fo', 'ba'])
array_2 = np.array(['lab', 'abc', 'zwf', 'foo', 'bar'])

for potential_word in array_2:
    for word_to_search in array_1:
        if word_to_search in potential_word:
          result_list.append(potential_word)
          break
print(result_list)
票数 0
EN

Stack Overflow用户

发布于 2021-03-23 05:06:58

您可以使用现有的短路方法anyall;在这里,您只需要any

代码语言:javascript
复制
result_list = [word for word in array_2
               if any(digram in word for digram in array_1)]

结果:

代码语言:javascript
复制
['lab', 'abc', 'foo', 'bar']

您还可以使用filter

代码语言:javascript
复制
result_list = list(filter(lambda word: 
                           any(digram in word for digram in array_1), 
                       array_2)
票数 0
EN

Stack Overflow用户

发布于 2021-03-23 05:18:34

我不知道有什么技巧可以让它更快,但我有一些小的改进可以提供。在这种情况下,使用numpy.arrays没有任何效果,因为您无论如何都是手动遍历单个条目。只有当有一些numpy方法可以帮助我们完成任务时,数组才能提供优势。目前,我建议在匹配后从list_2中删除条目,并使用while循环检查list_2是否仍有条目。

编辑

从一开始就使用set逻辑实际上似乎更快一点。我已经添加了这个方法。

以下是一些基本的速度比较和@Prune's的建议:

代码语言:javascript
复制
from time import time


def original(list_1, list_2, result_list):
    for word_to_search in list_1:
        for potential_word in list_2:
            if word_to_search in potential_word:
                result_list.append(potential_word)
    return list(set(result_list))


def while_loop(list_1, list_2, result_list):
    i = 0
    while i < len(list_1) and list_2:
        word_to_search = list_1[i]
        for potential_word in list_2:
            if word_to_search in potential_word:
                result_list.append(potential_word)
                list_2.remove(potential_word)
        i += 1

    return result_list


def set_(list_1, list_2, result_list):
    result_set = set()
    for word_to_search in list_1:
        for potential_word in list_2:
            if word_to_search in potential_word:
                result_set.add(potential_word)
    return list(result_set)


def any_(list_1, list_2, result_list):
    return [
        word for word in list_2 if any(digram in word for digram in list_1)
    ]


def filter_(list_1, list_2, result_list):
    return list(
        filter(lambda word: any(digram in word for digram in list_1), list_2)
    )


methods = {
    'original': original,
    'while_loop': while_loop,
    'any': any_,
    'filter': filter_,
}

result_list = []
list_1 = ['ab', 'fo', 'ba']
list_2 = ['lab', 'abc', 'zwf', 'foo', 'bar']
for name, method in methods.items():
    start = time()
    for i in range(10000):
        method(list_1, list_2, result_list)
    stop = time()
    print(f'{name}: {stop-start}')

返回:

代码语言:javascript
复制
original: 1.475600004196167
while_loop: 0.006448030471801758
set: 0.004959821701049805
any: 0.006943941116333008
filter: 0.008928060531616211

根据您的实际数据,这可能是完全关闭的。

编辑

我觉得可能会有一些很好的方法来使用list_2.__str__()和一些字符串方法,这将是非常快的,但我现在想不出一个。您也可以使用regex,但这样做可能会很慢。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66753680

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档