首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在距离k处检测等量元素的有效函数

在距离k处检测等量元素的有效函数
EN

Stack Overflow用户
提问于 2022-04-28 08:25:27
回答 3查看 71关注 0票数 -1

我正在寻找一个有效的函数,在距离为k的列表中找到相等的元素。

输入示例:

代码语言:javascript
运行
复制
v=['a','c','d','e','a','c','e','e','e','d']
k=4 

期望产出:

代码语言:javascript
运行
复制
['a', 'c', 'e']

原因:a同时位于0和4 4-0=k,c同时位于1和5-1=k,e同时位于3和7-3=k。

如果可能的话,我正在寻找比用for循环逐个元素循环更有效的东西。也就是说,我在寻找比以下更好的东西:

代码语言:javascript
运行
复制
def dist_k(k, v):
    v_len = len(v)
    out = []
    for i in range(0,v_len,1):
        if i+k < v_len:
            if v[i] == v[i+k]:
                out.append(v[i])
    print(out)   
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-04-28 08:32:04

编辑

我找到了一种聪明的方法,可以更快地做到这一点,而不需要np.roll,而且不会将数组视为循环:

代码语言:javascript
运行
复制
>>> import numpy as np
>>> v = ['a','c','d','e','a','c','e','e','e','d']
>>> v_np = np.array(v)
>>> k = 4
>>> v_init = v_np[:-k]
>>> v_init[v_init == v_np[k:]]
array(['a', 'c', 'e'])

这样做的想法是,在没有最后一个k元素的情况下存储数组的起始(因为在它们之后有比k元素更少的元素)。我存储数组,因为我需要它两次。

代码语言:javascript
运行
复制
>>> v_init = v_np[:-k]
>>> v_init
array(['a', 'c', 'd', 'e', 'a', 'c'])

然后,我使用数组的第二部分,没有第一个k元素:

代码语言:javascript
运行
复制
>>> v_np[k:]
array(['a', 'c', 'e', 'e', 'e', 'd'])

然后我可以比较这两个数组:

代码语言:javascript
运行
复制
>>> v_init == v_np[k:]
array([ True,  True, False,  True, False, False])

最后,我可以从v_init (而不是从v )获得与索引对应的元素(因为数组的长度不匹配):

代码语言:javascript
运行
复制
>>> v_init[v_init == v_np[k:]]
array(['a', 'c', 'e'])

由于Performances使用numpy (它使用C进行计算),这个方法在使用大数组时要快得多。但是,由于向numpy数组的转换,对于小列表(甚至不确定,请用您的问题尝试一下),它可能会慢一些:

代码语言:javascript
运行
复制
def list_comprehension(v, k):
    return [v[i] for i in range(len(v)-k) if v[i] == v[i+k]]

def using_numpy(v, k):
    v_np = np.array(v)
    v_init = v[:-k]
    return v_init[v_init == v[k:]]

>>> from timeit import timeit
>>> v = np.random.rand(100000).tolist()  # I consider that the input is a simple list
>>> timeit(lambda: list_comprehension(v,k), number=1000)
7.875344538999343
>>> timeit(lambda: using_numpy(v,k), number=1000)
3.646597085000394

圆周数组的原始答案

代码语言:javascript
运行
复制
import numpy as np
v = np.array(['a','c','d','e','a','c','e','e','e','d'])
k = 4
v[v == np.roll(v,-k)]

基本上,np.roll通过k元素移动数组,然后将初始数组与移位数组进行比较,并保留它们相等的元素:

代码语言:javascript
运行
复制
>>> np.roll(v, -k)
array(['a', 'c', 'e', 'e', 'e', 'd', 'a', 'c', 'd', 'e'])
>>> v == np.roll(v,-k)
array([ True,  True, False,  True, False, False, False, False, False,
       False])
>>> v[v == np.roll(v,-k)]
array(['a', 'c', 'e'])

请注意,此方法将考虑数组是循环的,即它将数组的第一个和最后一个值视为相邻的:

代码语言:javascript
运行
复制
>>> v=np.array(['a','c','d','e','a','c','e','e','e','d', 'a'])
>>> v[v == np.roll(v,-k)]
array(['a', 'c', 'e', 'd'])
票数 2
EN

Stack Overflow用户

发布于 2022-04-28 08:34:30

您可以尝试以下代码:

代码语言:javascript
运行
复制
    v=['a','c','d','e','a','c','e','e','e','d']
    k=4 

    result = [v[i] for i in range(len(v)-k) if v[i] == v[i+k] ]
票数 0
EN

Stack Overflow用户

发布于 2022-04-28 09:06:24

我不知道这是否比其他建议更有效,但这是另一种选择:

代码语言:javascript
运行
复制
v = ['a', 'c', 'd', 'e', 'a', 'c', 'e', 'e', 'e', 'd']
k = 4
print([e for e, f in zip(v, v[k:]) if e == f])

输出:

代码语言:javascript
运行
复制
['a', 'c', 'e']
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72040347

复制
相关文章

相似问题

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