2

给定以下数据:

a = ["onee", "two", "three"]
b = ["one", "four"]

我想要一些测试,例如:

[True if x in a else False for x in b]

返回

[True, False]

代替

[False, False]

所以对于 list 中的每个元素b,我想看看它是否是 list 中任何元素的子字符串a

可以做到这一点的一种方法如下:

test = []
for elb in b:
    included = False
    for ela in a:
        if elb in ela:
            included = True
        break
    test.append(included)

我不觉得这是一个很好的方法,也许有一种理解可以改进它?

以下也有效:

[True if any(elb in ela for ela in a) else False for elb in b]

我只是在想可能会有更好的方法。

4

4 回答 4

3

首先,这

True if True else False

是多余的。所以在你的第一个比赛中。你可以只拥有:[x in a for x in b],同样,[any(elb in ela for ela in a) for elb in b]

而且我认为这很短,就角色而言,你会得到它。

然而,为了提高效率,您可以从 中的所有字符串预先生成所有可能的子字符串a,并将它们存储在set.

这将意味着复杂性将从O(n*m*p),其中n是 的长度bm是 的长度a,并且n是 的平均子字符串长度a,减少到简单的O(n)。这是因为,一旦创建了子字符串查找集,检查特定元素b是一项O(1)操作,因为您正在检查是否包含在集合中,而不是O(m*p)您必须检查每个元素的每个子字符串a

要生成此子字符串查找集,您可以使用集合推导:

a_substrings = {s[i:j] for s in a for i in range(len(s)) for j in range(i+1, len(s)+1)}

那么你可以检查in这个:

[s in a_substrings for s in b]

[True, False]这为您的输入提供了预期。


这真的更快吗?

对于小型列表ab列表,创建查找集的开销将超过能够检查b. 此外,对于包含 long甚至中等大小的超长a列表,花时间遍历所有子字符串并创建查找集可能会再次变慢,尤其是如果其中的大多数元素都将在 的前几个字符串内匹配。stringsbaba

但是,在两个列表都很长的情况下,最重要的是何时b很长,您的方法将不断生成并a一遍又一遍地检查b. 显然,这比预先计算子集要慢。我想这本质上是搜索引擎的一个关键优化——当有人提出一个查询时,他们不会每次都从一张白纸开始拖网,而是不断地重新评估所有已知的网站,当然是按照受欢迎程度的顺序,这样当查询进来时,它们就“准备好了”。

于 2020-05-03T19:53:04.883 回答
2

这是我提出的另一种方法:

[x in "-".join(y for y in a) for x in b]

将所有字符串连接a到一个字符串中并测试元素是否在其中。

输出:

[True, False]

免责声明:不确定这是否正是“更好”,但同样,这只是另一种方法。

于 2020-05-03T19:36:18.027 回答
1

你可以做:

>>> [ y.startswith(x) for x, y in zip(b,a)]
[True, False]
>>> 
于 2020-05-03T19:46:04.327 回答
1

这就够了:

[ any(elb in ela for ela in a) for elb in b ]
于 2020-05-03T19:29:09.813 回答