查找具有可自定义数字之间距离的数字运行

Posted

技术标签:

【中文标题】查找具有可自定义数字之间距离的数字运行【英文标题】:Find number runs with customizable distance between numbers 【发布时间】:2018-11-19 16:14:10 【问题描述】:

我有一个排序的整数列表,我想找到这个列表中的数字。在寻找以 1 为增量的数字运行时,我已经看到了很多示例,但我也想寻找数字之间的差异可自定义的数字运行。

例如,假设我有以下数字列表:

nums = [1, 2, 3, 6, 7, 8, 10, 12, 14, 18, 25, 28, 31, 39]

使用找到的示例 here,我能够找到以下运行次数:

[[1, 2, 3], [6, 7, 8], [10], [12], [14], [18], [25], [28], [31], [39]]

但是,我想查找两个数字之间的差可能不仅仅是 1 的数字运行。例如,我希望所有数字运行的距离小于或等于 2。

[[1, 2, 3], [6, 7, 8, 10, 12, 14], [18], [25], [28], [31], [39]] 

或者也许我希望所有数字运行的距离小于或等于 3。

[[1, 2, 3, 6, 7, 8, 10, 12, 14], [18], [25, 28, 31], [39]]

这是我现在正在使用的函数,用于获取距离为 1 的数字运行。

def runs(seq, n):
    result = []
    for s in seq:
        if not result or s != result[-1][-1] + n:
            # Start a new run if we can't continue the previous one.
            result.append([])
        result[-1].append(s)
    return result

使用当前函数,如果我设置n=1,那么我会找到所有连续的数字序列。如果我设置n=2,那么我只会找到[8, 10, 12, 14]。如何修改此函数以查找小于或等于 n 的运行次数?

我希望能够做到这一点:

runs(num, 2)
[[1, 2, 3], [6, 7, 8, 10, 12, 14], [18], [25], [28], [31], [39]] 

【问题讨论】:

不就是s > result[-1][-1] + n而不是s != result[-1][-1] + n吗? 只是想指出这是一个写得很好,质量很高的问题,做得好! 我相信您在<=3 中的示例是错误的,就像在[..., [25, 28], [31], ...] 中一样,31 与 28 的距离只有 3。 【参考方案1】:

迭代for 分组

我只是用这个来修复你的代码。为简化起见,您可以将result 初始化为seq[0]

def runs(seq, n):
    result = [[seq[0]]]
    for s in seq[1:]:
        if s - result[-1][-1] > n:  # Keep it simple. Compare the delta.
            result.append([])
        result[-1].append(s)

    return result

>>> runs(nums, 1)
[[1, 2, 3], [6, 7, 8], [10], [12], [14], [18], [25], [28], [31], [39]]
>>> runs(nums, 2)
[[1, 2, 3], [6, 7, 8, 10, 12, 14], [18], [25], [28], [31], [39]]

pandas.GroupBy

如果你想变得花哨,你可以使用 groupby 成语,用 pandas 很容易。

import pandas as pd

def runs2(seq, n):
    s = pd.Series(seq)
    return s.groupby(s.diff().gt(n).cumsum()).apply(pd.Series.tolist).tolist()

>>> runs2(nums, 3)
[[1, 2, 3, 6, 7, 8, 10, 12, 14], [18], [25, 28, 31], [39]]

这里有两个基本要素:grouper(您要分组的谓词)和 agg 函数(您将应用于每个组的函数)

石斑是s.diff().gt(n).cumsum(),细分算三件事:

    seq 中使用 diff 的元素差异 一个布尔掩码,指示差异是否大于n 执行累积和(或计数)以确定组

这个操作的输出是

s.diff().gt(n).cumsum()

0     0
1     0
2     0
3     1
4     1
5     1
6     1
7     1
8     1
9     2
10    3
11    4
12    5
13    6
dtype: int64

agg 函数是pd.Series.tolist,它将任何系列转换为列表。这就是我们需要的,一个嵌套列表。

【讨论】:

【参考方案2】:
def runs(nums, n):
    idx = np.flatnonzero(np.ediff1d(nums, n + 1, n + 1) > n)
    return [nums[i1:i2] for i1, i2 in zip(idx[:-1], idx[1:])]

那么,

>>> runs(nums, 3)
[[1, 2, 3, 6, 7, 8, 10, 12, 14], [18], [25, 28, 31], [39]]

【讨论】:

【参考方案3】:
In [4]: def runs(seq, n):
   ...:     indexs = [i for i in range(len(seq)) if i==0 or seq[i]-seq[i-1]>n]
   ...:     return [seq[a:b] for a, b in zip(indexs, indexs[1:]+[len(seq)])]
   ...: 
   ...: 

In [5]: runs(nums, 3)
Out[5]: [[1, 2, 3, 6, 7, 8, 10, 12, 14], [18], [25, 28, 31], [39]]

In [6]: runs(nums, 2)
Out[6]: [[1, 2, 3], [6, 7, 8, 10, 12, 14], [18], [25], [28], [31], [39]]

【讨论】:

以上是关于查找具有可自定义数字之间距离的数字运行的主要内容,如果未能解决你的问题,请参考以下文章

OpenLayers动态测量距离和面积,并可自定义测量的线样式

Kotlin--›自定义实现支付密码数字键盘

php生成随机密码(php自定义函数)转自先锋教程网

可生成/管理/可自定义地址的 短链接URL网站

具有自定义距离的层次聚类

csharp 具有一个可自定义属性的简单SharePoint WebPart示例