【问题标题】:Python find subsets positionsPython找到子集位置
【发布时间】:2018-06-24 17:05:11
【问题描述】:

我有一个非常大的列表,想检查子集的位置,我试试这个:

l = ['7', '10', '8', '8', '6', '13', '7', '10', '13', '13', 
'7', '11', '9', '7', '15', '9', '10', '13', '6', '16']

print(set(['10', '13']).issubset(set(l)))

k= []
for i in range(0, len(l) - 1):
    if l[i] == '10' and l[i + 1] == '13':
        k.append(i)

print(k) 

#True
#[7, 16]

如果列表很大,我认为这不是 Python 的方式,那么有没有更好的方式?

【问题讨论】:

  • 你能给出示例输入和期望的输出吗?我在关注时遇到问题
  • 子集可能很大,而超集可能非常大
  • 您不是在搜索您认为的子集,因为 set(['10', '10']){'10'}
  • 您对任务感到困惑,您要查找子集还是子列表?

标签: python python-3.x list subset indices


【解决方案1】:

从很长的列表vll中切出一个子列表,sl长度切片len(sl)

看看它们是否等于if sl == vll[i:i+len(sl)]

递增ifor i in range(len(vll)-len(sl)+1)

vll = ['7', '10', '8', '8', '6', '13', '7', '10', '10', '13', 
'7', '11', '9', '7', '15', '9', '10', '10', '6', '16']

sl = ['10', '10']

[i for i in range(len(vll)-len(sl)+1) if sl == vll[i:i+len(sl)]]

Out[986]: [7, 16]

【讨论】:

    【解决方案2】:

    最 Pythonic 的方式是什么?嗯...这取决于您要完成什么以及您想要优化什么...

    如果您的用例只需要在一次代码运行中检查单个子集的存在性和位置...您拥有的代码就足够了。根据您的“大型列表”的数据源,生成器可以帮助您提高内存效率,但我认为这不是您所追求的。

    由于您有针对特定挑战的工作代码,我猜您希望优化这些“子集查找”的性能 - 这意味着您需要检查列表中是否存在多个子集(对?)。如果是这样,为了优化查找速度(以内存为代价),您可以遍历长列表一次并在 Python 字典中构建所有子集及其位置的索引,如下所示:

    from collections import defaultdict
    
    large_list = ['7', '10', '8', '8', '6', '13', '7', '10', '10', '13', '7', '11',
                  '9', '7', '15', '9', '10', '10', '6', '16']
    
    indexed_subsets = defaultdict(list)
    
    for i in range(len(large_list)-1):
        subset = (large_list[i], large_list[i+1])
        indexed_subsets[subset].append(i)
    
    
    # Test if subset exists
    print(('10', '10') in indexed_subsets)
    
    # Print locations where the subset exists
    print(indexed_subsets.get(('10', '10')))
    
    # Output:
    # True
    # [7, 16]
    

    这种方法的好处是检查子集的存在和获取子集的位置总是fastO(1) vs.O(n));虽然字典会比您想要处理的已经“大列表”大得多。

    ...这完全取决于您想要优化的内容。 ?

    【讨论】:

    • 您的代码似乎适用于非常大的列表。 [22570, 93853, 150320] 已用时间:0.1750638484954834 s [22570, 93853, 150323] 已用时间:0.03659486770629883 s False None 最后一个已用时间:0.2751467227935791 s。
    • 我不确定您传递了哪些输入,也不确定您是在进行单个查找还是多个查找。由于您的问题并不清楚,我假设您想要查找长度为两个元素(对)的子集,并希望优化执行多个查找的速度。
    • 如果您想查找任意长的子集,那么接受的解决方案中的代码可能是您最好的选择 - 使用列表理解的语法糖,它可以合理地理解和简洁。
    • 如果您确实需要优化多个查找的速度(是的,单个查找会更慢,因为您必须建立索引然后进行查找)并使用任意长的子集进行此操作,您仍然可以创建子集索引,但它会很大并且需要时间来构建。建立索引需要时间,但单个查找将比线性搜索每个子集 O(1) 与 O(n) 的长列表更快。
    【解决方案3】:

    这种方式比较快,不知道有没有比这个更快的方式:

    s_vll  = str(vll)
    s_sl = str(sl).replace("[", "").replace("]", "")
    nl = s_vll.split(s_sl) 
    p = []
    c = 0
    if len(nl) > 1:
        for i in range(0, len(nl) -1):
            c += nl[i].count(",") + i * (len(sl) - 1)
            p.append(c) 
    print(p)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 2010-09-21
      相关资源
      最近更新 更多