【问题标题】:Comparing elements in a list with its neighbours将列表中的元素与其邻居进行比较
【发布时间】:2017-12-11 18:00:38
【问题描述】:

我在 Python 中有一个包含 29400 个值的列表,我正在尝试检查列表中的每个元素是否大于其左侧的 2000 个邻居和右侧的 2000 个邻居。如果元素大于其 4000 个邻居,我想检索元素的索引。如果右侧没有 2000 个邻居,我只想将其与未来的元素进行比较,直到到达列表末尾,反之亦然,如果左侧没有 2000 个值。

def find_peaks(t):
prev = []
future = []
peak_index = []
for i in range(len(t)-2000): # compare element with previous values
    for j in range(1,2001):
        if t[i]<t[i+j]:
            prev.append(False)
            break
        if j==2000:
            if t[i]<t[i+j]:
                prev.append(False)
                break
            prev.append(True)

for i in range(1999,len(t)-1): # compare element with future values
    for j in range(1,2001):
        if t[i]<t[i-j]:
            future.append(False)
            break
        if j==2000:
            if t[i]<t[i-j]:
                future.append(False)
                break
            future.append(True)
future = future[::-1] # reverse list
for i in range(0,len(prev)-1):
    if prev[i] == True:
        if prev[i] == True:
            peak_index.append(i)

有没有人知道任何更好的方法来解决这个问题?我在比较列表末尾和开头附近的元素时遇到问题 - 如果列表中没有 2000 个元素可供我比较,那么列表会环绕到列表的开头,这不是什么我要。

【问题讨论】:

  • 您想要列表的循环行为吗?我的意思是,如果你的列表中有 10k 个元素,并且你正在比较第一个元素开始,那么它的左侧没有要比较的元素。所以你想把它和后端进行反向比较吗?还是您跳过左侧的比较?我说得够清楚了吗?
  • 不,我不想要循环行为。如果我要比较第三个元素,我只想将它与左侧的第一个和第二个元素以及右侧的 2000 个元素进行比较。我是 python 和一般编程的新手,可能有一种更简单的方法,我只是不知道。
  • 好的,我明白了,感谢您的澄清。

标签: python


【解决方案1】:

我的解决方案不涉及任何语言强大的内置方法。找到目标峰值只是简单的逻辑。基本上,我遍历每个元素,然后在内部循环中检查其先前或将来的邻居是否存在并且小于当前元素。我正在将isPeak 变量初始化为True,因为如果两个方向上的邻居都没有大于当前元素,则表明您的当前元素是峰值元素。之后只是获取目标元素的索引。

def find_peaks(t , neighbour_length=2000):
    peak_index = []
    for i in range(len(t)): # compare element with previous values
        isPeak = True #intialize to true
        for j in range(i, neighbour_length + i):

            # Check if previous index value is present
            if (2*i-j-1 >= 0):
                # Check if next neighbour is less or break
                if(t[i] <= t[2*i-j-1]):
                    isPeak = False
                    break
            # Check if Future element is present
            if (j+i+1 < len(t)):
                #Check if next future neighbour ir less or break
                if(t[i] <= t[i+j+1]):
                    isPeak = False
                    break

        if(isPeak):
            peak_index.append(i)

    return peak_index

希望对你有帮助!

【讨论】:

    【解决方案2】:

    一个幼稚的迭代版本是遍历每个元素并向后/向前看一定次数,看看是否有大于它的值,如果没有,则将其视为一个选择:

    def find_peaks(data, span=2000):
        peaks = []
        for i, value in enumerate(data):
            peak = False  # start with the assumed non-peak
            for j in range(max(0, i - 1), max(0, i - span - 1), -1):  # look behind
                peak = value > data[j]  # check if our value is larger than the selected neighbor
                if not peak:  # not a peak, break away
                    break
            if peak:  # look behind passed, look ahead:
                for j in range(i + 1, min(i + span + 1, len(data))):
                    if value <= data[j]:  # look ahead failed, break away
                        peak = False
                        break
                if peak:  # if look ahead passed...
                    peaks.append(i)  # add it to our peaks list
        return peaks
    

    这是执行前/后查看的最高效方法,因为它会在不满足条件时立即中断,而不是使用每个元素检查每个元素。

    如果您想在计算峰值时计算具有相同值的邻居(因此您当前的峰值候选者相同),您可以在后视部分使用peak = value &gt;= data[j],在前瞻部分使用if value &lt; data[j] .

    【讨论】:

      【解决方案3】:

      您可以使用一些列表推导,这样实际的搜索就变成了单行。我无法判断速度和美观,但在我的机器上只需要几秒钟。

      import random
      
      # create list of random numbers and manually insert two peaks
      t = [random.randrange(1, 1000) for r in range(29400)]  # found this here: https://stackoverflow.com/questions/16655089/python-random-numbers-into-a-list
      t[666] = 2000
      t[6666] = 2000
      
      # finds the peak elements
      peaks = [index for index, value in enumerate(t) if value == max(t[max(index-2000, 0):min(index+2000, len(t))])]
      print peaks  # includes 666 and 6666
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-06-06
        • 2015-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多