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



我有一个整数的排序列表,我发现想要找到这个列表中的数字运行。 在寻找以 1 递增的数字运行时,我看过很多例子,但我也想寻找数字之间的差异是可自定义的数字运行。

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

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

使用此处找到的示例,我能够找到以下数字运行:

[[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]] 

带有for迭代分组

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

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成语,让熊猫变得容易。

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]]

这里有两个基本成分:石斑鱼(您正在分组的谓词(和 agg 函数(您将应用于每个组的函数(

石斑鱼s.diff().gt(n).cumsum(),分解计算三件事:

  1. 使用diffseq的元素差异
  2. 指示差异是否大于n的布尔掩码
  3. 执行累积总和(或计数(以确定组

此操作的输出为

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的,并将任何序列转换为列表。这就是我们在这里需要的,一个嵌套列表。

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]]
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]]

最新更新