如何接近数值范围列表

2024-09-30 01:21:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试决定迭代一系列值以找到包含其他范围的范围的最佳方法。 i、 e.范围8-18包括范围10-14

my_range_list = [[1, 1], [2, 8], [3, 16], [4, 16], [15, 25],[14,26]]
# should be the following:
# 3,16 encompasses 4,16 (4-16)
# 3,16 does not encompass 2,8 (2-8)

largest_range_list = []
for my_range in my_range_list:
    my_lowr = my_range[0]
    my_hir = my_range[1]

    new_range_list =[]
    encompassed=0
    for largest_range in largest_range_list:
        largest_lowr = largest_range[0]
        largest_hir = largest_range[1]

        if (my_lowr < largest_lowr) and (my_hir > largest_hir):
            new_range_list.append(my_range)
            encompassed = 1
            break
        if (largest_lowr <= my_lowr) and (largest_hir >= my_hir):
            new_range_list.append(largest_range)
            encompassed = 1
            break
        new_range_list.append(largest_range)
    largest_range_list = new_range_list
    if (not(encompassed == 1)):
        largest_range_list.append(my_range)
print ("largest_range_list=" +  ' '.join(map(str, largest_range_list)))

后来我考虑过替换,但那不起作用,因为large_range_list处于不断变化的状态。还想知道哪种方式最适合python(我来自Perl)。你知道吗

我应该看什么?起始列表是良好的结构还是应该有所不同(范围列表)?你知道吗


Tags: andinnewforifmynotrange
3条回答

您可以将迭代简化为:

my_range_list = [[1, 1], [2, 8], [3, 16], [4, 16], [5, 25]]
large_range_list = [[1, 1]]

for my_lowr, my_hir in my_range_list:
    for large_lowr, large_hir in large_range_list:
        if (my_lowr <= large_lowr) and (my_hir >= large_hir):
            print("Range ({}, {}) encompasses ({}, {}).".format(
                my_lowr, my_hir, large_lowr, large_hir))

我已经更改了条件以匹配您的示例(3,16 encompasses 4,16 (4-16))。你知道吗

如果没有更改,它将无法工作,因为正确的边界重叠,并且使用原始条件(my_hir > large_hir),它将拒绝有效范围。左侧也一样。你知道吗

如果你想一次完成。。。我会这样做。。。你知道吗

myRanges   = [(1,1),(2,8),(3,16),(4,16),(5,25)]
testRanges = [(0,0),(1,1),(2,8),(3,16),(5,25)]

[    str((tLo,tHi)) + ' IS enc by '  + str((mLo, mHi)) if (tLo >= mLo and tHi <= mHi)
else str((tLo,tHi)) + ' NOT enc by ' + str((mLo, mHi))
for tLo,tHi in testRanges 
for mLo,mHi in myRanges]

根据你的需要。。。如果您不需要按顺序对它们进行操作(在本例中,通过打印一些内容),那么这是一种更干净的方法。你知道吗

encompassed = [
    ((tLo,tHi),(mLo, mHi))
    for tLo,tHi in testRanges 
    for mLo,mHi in myRanges
    if (tLo >= mLo and tHi <= mHi)]

notEncompassed = [
    ((tLo,tHi),(mLo, mHi))
    for tLo,tHi in testRanges 
    for mLo,mHi in myRanges
    if (tLo < mLo or tHi > mHi)]

然后对它们采取行动,建立一个功能。。。。你知道吗

def printResults(resultList, printString):
    for t,m in resultList:
        print str(t) + ' ' + printString + ' ' + str(m)
printResults(encompassed, 'encompassed by')

(1, 1) encompassed by (1, 1)
(2, 8) encompassed by (2, 8)
(3, 16) encompassed by (3, 16)
(5, 25) encompassed by (5, 25)

我把你的列表转换成元组列表,因为它们的长度总是2。。。但是语法在列表列表上也可以很好地工作。你知道吗

此外,一般来说,列表理解是更'pythonic'的方式,而不是简单的事情嵌套for循环。。。你知道吗

[(x,y) for x in [1,2,3] for y in [5,6,7] if x < 3]

最好是

for x in [1,2,3]:
    for y in [5,6,7]:
        if x < 3:
            print (x,y)

测试一个范围是否包含在另一个范围中的更简单的函数:

my_ranges = [[1, 1], [2, 8], [3, 16], [4, 16], [15, 25], [14, 26]]

is_encompassed_by = lambda a, b: a != b and (a[0] >= b[0] and a[1] <= b[1])

通过排列可以将每个范围与其他范围进行比较:

from itertools import permutations

encompassed_ranges = []
for a, b in permutations(my_ranges, 2):
    if a not in encompassed_ranges: # to cut short if it is already there
        if is_encompassed_by(a, b):
            encompassed_ranges.append(a)

not_encompassed_ranges = [r for r in my_ranges if r not in encompassed_ranges]

如果原始列表中有重复项,则最终列表可能有重复项。你知道吗

编辑:我的第一种方法如下,但考虑到ShadowRanger的相关评论,我将其更改为上面的解决方案

您可以使用Python中可用于处理集合的操作来处理它:

rng_to_set = lambda rng: set(range(rng[0], rng[1]))

encompasses = lambda a, b: rng_to_set(a).issuperset(rng_to_set(b))
encompassed_by = lambda a, b: rng_to_set(a).issubset(rng_to_set(b))

l = [[1, 1], [2, 8], [3, 16], [4, 16], [5, 25]]
print ( encompasses( l[2] , l[3] ) )  # True
print ( encompassed_by( l[4] , l[2] )) # False
print ( encompassed_by( l[3] , l[2] )) # True

相关问题 更多 >

    热门问题