wsdzbm
wsdzbm

Reputation: 3670

How to merge some

I read a lot of lower and upper limits from text files and want to merge these limits. The data type is either float number or date string as yyyy-mm-dd (two independent cases).

Here, a short list of int boundaries, is just a simplified example for demonstration.

  # boundaries read from text files.
  b = [[-1, 2], [-2, 1], [0, 4], [3, 5], [-3, 1], [-10, -7], [6, 8]]

It's simple if only the lowest and highest limits are wanted.

  b = reduce(lambda x,y: [min(x[0], y[0]), max(x[1], y[1]], b)

But there are gaps in the data so that I need to get the gaps also. I expect results like

  # return a list merged limits
  [[-10, -7], [-3, 5], [6, 8]] 

or

  # return the limits and list of gaps
  [-10, 8], [[-7, -3], [5, 6]] 

How can I do that elegantly?

Upvotes: 0

Views: 49

Answers (2)

aldanor
aldanor

Reputation: 3481

If you like using reduce, you can still do it this way:

from functools import reduce

def join(acc, v):
    if not acc:
        return [v]
    last = acc.pop()
    if v[0] > last[1]:
        return acc + [last, v]
    return acc + [(last[0], max(last[1], v[1]))]

b = [[-1, 2], [-2, 1], [0, 4], [3, 5], [-3, 1], [-10, -7], [6, 8]]
print(reduce(join, sorted(b), []))

which outputs

[[-10, -7], (-3, 5), [6, 8]]

Upvotes: 1

Alex Hall
Alex Hall

Reputation: 36043

b = [[-1, 2], [-2, 1], [0, 4], [3, 5], [-3, 1], [-10, -7], [6, 8]]
b.sort()
result = []
current = b[0]
for interval in b[1:]:
    if current[1] >= interval[0]:
        current[1] = interval[1]
    else:
        result.append(current)
        current = interval
result.append(current)
print(result)  # [[-10, -7], [-3, 5], [6, 8]]

Upvotes: 1

Related Questions