Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 确定有序子列表是否位于大型列表中的最快方法?_Python_List_Nested Lists - Fatal编程技术网

Python 确定有序子列表是否位于大型列表中的最快方法?

Python 确定有序子列表是否位于大型列表中的最快方法?,python,list,nested-lists,Python,List,Nested Lists,假设我有一个巨大的列表,其中包含2000000个列表,每个列表的长度约为50 我想通过丢弃序列中不包含两个元素的子列表来缩短2000000个我的\u庞大的\u列表 到目前为止,我已经: # https://stackoverflow.com/questions/3313590/check-for-presence-of-a-sliced-list-in-python def check_if_list_is_sublist(lst, sublst): #checks if a list

假设我有一个巨大的列表,其中包含2000000个列表,每个列表的长度约为50

我想通过丢弃序列中不包含两个元素的子列表来缩短2000000个
我的\u庞大的\u列表

到目前为止,我已经:

# https://stackoverflow.com/questions/3313590/check-for-presence-of-a-sliced-list-in-python
def check_if_list_is_sublist(lst, sublst):
    #checks if a list appears in order in another larger list.
    n = len(sublst)
    return any((sublst == lst[i:i + n]) for i in xrange(len(lst) - n + 1))

my_huge_list_of_lists = [x for x in my_huge_list_of_lists
                            if not check_if_list_is_sublist(x, [a,b])]
my_huge_list_of_lists = [x for x in my_huge_list_of_lists
                            if not check_if_list_is_sublist(x, [b,a])]
搜索词[a,b]或[b,a]的连续性很重要,因此我不能使用
set.issubset()

我觉得这很慢。我想加快速度。我考虑了一些选项,如使用“提前退出”和声明:

my_huge_list_of_lists = [x for x in my_huge_list_of_lists
                            if (a in x and not check_if_list_is_sublist(x, [a,b]))]
my_huge_list_of_lists = [x for x in my_huge_list_of_lists
                            if not (check_if_list_is_sublist(x, [a,b])
                                    or check_if_list_is_sublist(x, [b,a]))]
使用
语句的
for
循环中的次数更少:

my_huge_list_of_lists = [x for x in my_huge_list_of_lists
                            if (a in x and not check_if_list_is_sublist(x, [a,b]))]
my_huge_list_of_lists = [x for x in my_huge_list_of_lists
                            if not (check_if_list_is_sublist(x, [a,b])
                                    or check_if_list_is_sublist(x, [b,a]))]
并致力于加速功能(WIP)

并对堆栈溢出进行了搜索;但是想不出办法,因为调用
check\u if\u list\u is\u sublist()
的次数是
len(我的庞大列表)*2

编辑:根据请求添加一些用户数据

from random import randint
from string import ascii_lowercase
my_huge_list_of_lists = [[ascii_lowercase[randint(0, 25)] for x in range(50)] for y in range(2000000)]
my_neighbor_search_fwd = [i,c]
my_neighbor_search_rev = my_neighbor_search_fwd.reverse()

将n大小的子序列中的项解包为n个变量。然后写一个列表理解来过滤列表,检查子列表中的a、b或b、a


将n大小的子序列中的项解包为n个变量。然后写一个列表理解来过滤列表,检查子列表中的a、b或b、a


所以,我想不出任何聪明的算法检查来真正减少这里的工作量。但是,您在代码中执行了大量分配,并且迭代太多。所以,仅仅把一些声明移出函数就有点让我抓狂了

sublst = [a, b]
l = len(sublst)
indices = range(len(sublst))
def check_if_list_is_sublist(lst):
    for i in range(len(lst) - (l -1)):
        if lst[i] == sublst[0] and lst[i+1] == sublst[1]:
            return True
        if lst[i] == sublst[1] and lst[i + 1] == sublst[0]:
            return True
    return False

my_huge_list_of_lists = [x for x in my_huge_list_of_lists
                           if not check_if_list_is_sublist(x)]

这将上述示例代码的运行时间减少了约50%。有了这么大的列表,产生更多的进程并划分工作可能会看到性能的提高。但是,我想不出任何方法来真正减少比较量…

因此,我想不出任何聪明的算法检查来真正减少工作量。但是,您在代码中执行了大量分配,并且迭代太多。所以,仅仅把一些声明移出函数就有点让我抓狂了

sublst = [a, b]
l = len(sublst)
indices = range(len(sublst))
def check_if_list_is_sublist(lst):
    for i in range(len(lst) - (l -1)):
        if lst[i] == sublst[0] and lst[i+1] == sublst[1]:
            return True
        if lst[i] == sublst[1] and lst[i + 1] == sublst[0]:
            return True
    return False

my_huge_list_of_lists = [x for x in my_huge_list_of_lists
                           if not check_if_list_is_sublist(x)]

这将上述示例代码的运行时间减少了约50%。有了这么大的列表,产生更多的进程并划分工作可能会看到性能的提高。我想不出任何方法来真正减少比较的数量,尽管…

对于一个大列表中的搜索匹配,我相信哈希(元素)然后构建索引将是一个很好的解决方案

您将获得的好处: 构建索引一次,节省时间供将来使用(无需为每次搜索重复循环)。 甚至,我们可以在启动程序时建立索引,然后在程序退出时释放它

下面的代码使用两种方法获取哈希值:hash()和str();有时,您应该根据特定场景自定义一个哈希函数

如果使用Stand(),代码看起来很简单,不需要考虑哈希冲突。但这可能会导致内存爆炸

对于hash(),我使用该列表保存所有具有相同hash值的sub_lst。您可以使用hash(sub_lst)%designed_length来控制hash大小(但它会增加hash冲突率)

以下代码的输出:

按散列:0.0002398660394852955
按str():0.00022884208565612796
按OP编号:0.3001317172469765
[以1.781s完成]
测试代码

from random import randint
from string import ascii_lowercase
import timeit

#Generate Test Data
my_huge_list_of_lists = [[ascii_lowercase[randint(0, 25)] for x in range(50)] for y in range(10000)]
#print(my_huge_list_of_lists)
test_lst = [['a', 'b', 'c' ], ['a', 'b', 'c'] ]
#Solution 1: By using built-in hash function
def prepare1(huge_list, interval=1): #use built-in hash function
    hash_db = {}
    for index in range(len(huge_list) - interval + 1):
        hash_sub = hash(str(huge_list[index:index+interval]))
        if hash_sub in hash_db:
            hash_db[hash_sub].append(huge_list[index:index+interval])
        else:
            hash_db[hash_sub] = [huge_list[index:index+interval]]
    return hash_db

hash_db = prepare1(my_huge_list_of_lists, interval=2)
def check_sublist1(hash_db, sublst): #use built-in hash function
    hash_sub = hash(str(sublst))
    if hash_sub in hash_db:
        return any([sublst == item for item in hash_db[hash_sub]])
    return False

print('By Hash:', timeit.timeit("check_sublist1(hash_db, test_lst)", setup="from __main__ import check_sublist1, my_huge_list_of_lists, test_lst, hash_db ", number=100))

#Solution 2: By using str() as hash function
def prepare2(huge_list, interval=1): #use str() as hash function
    return { str(huge_list[index:index+interval]):huge_list[index:index+interval] for index in range(len(huge_list) - interval + 1)}

hash_db = prepare2(my_huge_list_of_lists, interval=2)
def check_sublist2(hash_db, sublst): #use str() as hash function
    hash_sub = str(sublst)
    if hash_sub in hash_db:
        return sublst == hash_db[hash_sub]
    return False

print('By str():', timeit.timeit("check_sublist2(hash_db, test_lst)", setup="from __main__ import check_sublist2, my_huge_list_of_lists, test_lst, hash_db ", number=100))

#Solution 3: OP's current solution
def check_if_list_is_sublist(lst, sublst):
    #checks if a list appears in order in another larger list.
    n = len(sublst)
    return any((sublst == lst[i:i + n]) for i in range(len(lst) - n + 1))

print('By OP\'s:', timeit.timeit("check_if_list_is_sublist(my_huge_list_of_lists, test_lst)", setup="from __main__ import check_if_list_is_sublist, my_huge_list_of_lists, test_lst ", number=100))
如果您想从一个列表中删除匹配的元素,这是可行的,但效果是您可能需要为新列表重建索引。除非列表是链表,否则请保存索引中每个元素的指针。我只是在google
Python上搜索如何获取列表中某个元素的指针,但找不到任何有用的东西。如果有人知道怎么做,请毫不犹豫地分享你的解决方案。谢谢

下面是一个示例:(它生成一个新列表而不是返回原始列表,有时我们仍然需要从原始列表中筛选一些内容)


对于一个大列表中的搜索匹配,我相信哈希(元素)然后构建索引将是一个很好的解决方案

您将获得的好处: 构建索引一次,节省时间供将来使用(无需为每次搜索重复循环)。 甚至,我们可以在启动程序时建立索引,然后在程序退出时释放它

下面的代码使用两种方法获取哈希值:hash()和str();有时,您应该根据特定场景自定义一个哈希函数

如果使用Stand(),代码看起来很简单,不需要考虑哈希冲突。但这可能会导致内存爆炸

对于hash(),我使用该列表保存所有具有相同hash值的sub_lst。您可以使用hash(sub_lst)%designed_length来控制hash大小(但它会增加hash冲突率)

以下代码的输出:

按散列:0.0002398660394852955
按str():0.00022884208565612796
按OP编号:0.3001317172469765
[以1.781s完成]
测试代码

from random import randint
from string import ascii_lowercase
import timeit

#Generate Test Data
my_huge_list_of_lists = [[ascii_lowercase[randint(0, 25)] for x in range(50)] for y in range(10000)]
#print(my_huge_list_of_lists)
test_lst = [['a', 'b', 'c' ], ['a', 'b', 'c'] ]
#Solution 1: By using built-in hash function
def prepare1(huge_list, interval=1): #use built-in hash function
    hash_db = {}
    for index in range(len(huge_list) - interval + 1):
        hash_sub = hash(str(huge_list[index:index+interval]))
        if hash_sub in hash_db:
            hash_db[hash_sub].append(huge_list[index:index+interval])
        else:
            hash_db[hash_sub] = [huge_list[index:index+interval]]
    return hash_db

hash_db = prepare1(my_huge_list_of_lists, interval=2)
def check_sublist1(hash_db, sublst): #use built-in hash function
    hash_sub = hash(str(sublst))
    if hash_sub in hash_db:
        return any([sublst == item for item in hash_db[hash_sub]])
    return False

print('By Hash:', timeit.timeit("check_sublist1(hash_db, test_lst)", setup="from __main__ import check_sublist1, my_huge_list_of_lists, test_lst, hash_db ", number=100))

#Solution 2: By using str() as hash function
def prepare2(huge_list, interval=1): #use str() as hash function
    return { str(huge_list[index:index+interval]):huge_list[index:index+interval] for index in range(len(huge_list) - interval + 1)}

hash_db = prepare2(my_huge_list_of_lists, interval=2)
def check_sublist2(hash_db, sublst): #use str() as hash function
    hash_sub = str(sublst)
    if hash_sub in hash_db:
        return sublst == hash_db[hash_sub]
    return False

print('By str():', timeit.timeit("check_sublist2(hash_db, test_lst)", setup="from __main__ import check_sublist2, my_huge_list_of_lists, test_lst, hash_db ", number=100))

#Solution 3: OP's current solution
def check_if_list_is_sublist(lst, sublst):
    #checks if a list appears in order in another larger list.
    n = len(sublst)
    return any((sublst == lst[i:i + n]) for i in range(len(lst) - n + 1))

print('By OP\'s:', timeit.timeit("check_if_list_is_sublist(my_huge_list_of_lists, test_lst)", setup="from __main__ import check_if_list_is_sublist, my_huge_list_of_lists, test_lst ", number=100))
如果您想从一个列表中删除匹配的元素,这是可行的,但效果是您可能需要为新列表重建索引。除非列表是链表,否则请保存索引中每个元素的指针。我只是在google
Python上搜索如何获取列表中某个元素的指针,但找不到任何有用的东西。如果有人知道怎么做,请毫不犹豫地分享你的解决方案。谢谢

下面是一个示例:(它生成一个新列表而不是返回原始列表,有时我们仍然需要从原始列表中筛选一些内容)


虽然这本身并不是你所说的“答案”,但它是一个基准测试框架,可以帮助你确定最快的方法来完成你想要的,因为它允许相对容易的修改以及添加不同的方法

我把答案放在c