【问题标题】:How do I efficiently overlay two strings where one string takes priority over the other?如何有效地覆盖两个字符串,其中一个字符串优先于另一个?
【发布时间】:2017-09-18 13:33:09
【问题描述】:

我有两个字符串作为文件范围的缓冲区。我想从这个“文件”中读取,以便从第一个字符串中读取字节,而不是第二个字符串,那里有重叠。

在下面的示例中,r1 和 r2 分别表示文件的范围,由字符串以及开始和结束偏移量组成。我已经对示例进行了格式化,以便更清楚地了解文件中字符串的存在位置。

def prioritized_read(range1, range2, read_start, read_end):
    # This is the bit I don't know how to write

r1 = ("ABCDEF", (0,6))
r2 = ( "DEF",   (1,4))
assert prioritized_read(r1, r2, 0, 6) == "ABCDEF"

r1 = ("ABC",    (0,3))
r2 = ( "DEF",   (1,4))
assert prioritized_read(r1, r2, 1, 4) == "BCF"

r1 = (  "ABC",  (2,5))
r2 = ("DEF",    (0,3))
assert prioritized_read(r1, r2, 0, 4) == "DEAB"

r1 = ( "A",     (1,2))
r2 = ("DEF",    (0,3))
assert prioritized_read(r1, r2, 0, 3) == "DAF"

r1 = ("ABC",    (0,3))
r2 = (   "DEF", (3,6))
assert prioritized_read(r1, r2, 3, 6) == "DEF"

read_startread_end 将始终以 r1r2 的端点为界。

这里的示例范围很小,但在我的应用程序中,它们可能大于 10 亿,因此我正在寻找一种时间和内存高效的解决方案。

我考虑将其发布到Programming Puzzles & Code Golf。看起来这应该是一个简单而明显的过程......但它打败了我。

注意我并没有真正从这里读取文件,所以我不能使用涉及 Python 文件对象的解决方案。我只是将文件用作一个方便的类比。

【问题讨论】:

  • 那么,您在阅读什么?你有内存中的所有数据吗?您正在阅读网络流吗?这可能会影响答案的性质。
  • 所有数据都会在内存中。

标签: python range overlap


【解决方案1】:

间隔应该被划分为子间隔。让我在这个例子中解释一下:

r1 = (  "ABC",  (2,5))
r2 = ("DEF",    (0,3))
assert prioritized_read(r1, r2, 0, 4) == "DEAB"

子区间的边界都是开始、结束的数字,即:0,2,3,4,5。 read_start 之前和 read_end 之后的数字可以忽略,因此 5 被淘汰。我们现在有0,2,3,4。不太明显的是,位于range1 内的range2 边界也可以被忽略,所以 3 也被排除在外。边界是0,2,4,这意味着子整数是0-22-4

剩下的很简单。我们从具有所需范围的数据源中读取 - 尊重优先级。范围不是从零开始的,因此必须考虑偏移量。

def prioritized_read(range1, range2, read_start, read_end):
    d1, r1 = range1
    d2, r2 = range2
    bset = set((read_start, read_end))
    for b in r1: 
        if read_start < b < read_end:
            bset.add(b)
    for b in r2: 
        if not r1[0] < b < r1[1] and read_start < b < read_end:
            bset.add(b)
    boundaries = sorted(bset)

    output = []
    for i in range(len(boundaries) - 1): 
        start, end = boundaries[i], boundaries[i+1]
        if r1[0] <= start < r1[1]:
            # read from #1
            output.append(d1[start-r1[0]:end-r1[0]])
        elif r2[0] <= start < r2[1]: 
            # read from #2
            output.append(d2[start-r2[0]:end-r2[0]])
        else:
            raise ValueError("no data source for {}:{}".format(start, end))
    return "".join(output)

【讨论】:

    【解决方案2】:

    这样的东西会给你想要的输出:

    def prioritized_read(r1, r2, start, end):
        s = [''] * max(r1[1][1], r2[1][1])
        s[r2[1][0]:r2[1][1]] = r2[0]
        s[r1[1][0]:r1[1][1]] = r1[0]
    
        return ''.join(s[start:end])
    

    这假定其中一个范围始终以0 开头,并且这些范围不是不相交的。如果范围很大,这可能不会节省内存

    【讨论】:

      猜你喜欢
      • 2013-08-22
      • 1970-01-01
      • 2011-05-13
      • 2021-12-06
      • 2015-01-04
      • 2015-04-22
      • 2019-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多