【问题标题】:Check if list element is a sub-element of those in another list with Python使用 Python 检查列表元素是否是另一个列表中的子元素
【发布时间】:2020-05-03 19:26:59
【问题描述】:

给定以下数据:

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

我想要一些测试,例如:

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

返回

[True, False]

代替

[False, False]

所以对于列表b 中的每个元素,我想看看它是否是列表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]

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

【问题讨论】:

    标签: python list inclusion


    【解决方案1】:

    首先,这个

    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) 降低,其中nb 的长度,ma 的长度,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 中每个元素的优势。此外,对于一个非常长的a 列表,包含很长的strings,甚至是一个中等大小的b,花时间遍历a 的所有子字符串并创建查找可能再次变慢设置,特别是如果b 中的大多数元素将在a 的前几个字符串中匹配。

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

    【讨论】:

    • 是的,这绝对是 OP 可以获得的 更好 方法。
    【解决方案2】:

    这是我想到的另一种方法:

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

    a的所有字符串合并为一个字符串,并测试该元素是否在其中。

    输出:

    [True, False]
    

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

    【讨论】:

    • 这有什么好处呢?
    • OP 要求另一种方法,这里是另一种方法。
    • 好吧,够公平的,我不确定我会说它更好,但 +1 更酷的东西。
    • 是的,当然也不确定它是否更好。让我在回答中澄清这一点,谢谢。
    • 是的 - 不确定它是否更好,但有其他方式看待事物总是好的,谢谢 :)
    【解决方案3】:

    这就够了:

    [ any(elb in ela for ela in a) for elb in b ]
    

    【讨论】:

      【解决方案4】:

      你可以这样做:

      >>> [ y.startswith(x) for x, y in zip(b,a)]
      [True, False]
      >>> 
      

      【讨论】:

      • 如果b中的字符串不在a中的字符串开头怎么办?例如:a = ["konee", "two", "three"]
      • 另外,当您执行zip(a, b) 时,您正在减少对a 前两个元素的查找,因为len(b) < len(a)
      • 然后,如果我们需要将其报告为 True,我们需要在 x 中使用 y。我只是关注问题和案例'one'和'onee'
      • 是的,这绝对只适用于与问题完全相同的情况。
      • 正确我们正在减少和优化事物,我们需要遍历短列表。没有必要循环较长的并检查较短的
      猜你喜欢
      • 2021-08-24
      • 2022-01-06
      • 2021-12-13
      • 2022-11-14
      • 2012-08-01
      • 1970-01-01
      • 2020-07-07
      • 1970-01-01
      • 2019-02-12
      相关资源
      最近更新 更多