Home > front end >  merge/Condense list based on condition
merge/Condense list based on condition

Time:07-09

Below example list -

a = [[0, 1], [3, 4], [5, 11], [12, 17], [20, 25], [26, 28]]

Expected Output

[[0,1], [3,17], [20,8]]

Logic

If we compare each element pairwise, if the difference of the last element of i-1 and first element of i is < 2, then condense the list to just represent the lower bound of the i-1 element and the upper bound of i.

This continues as covered in the example - element 2, 3 and 4 get merged from [3, 4], [5, 11], [12, 17] to just [3,17].

What I have tried

a = [[0, 1], [3, 4], [5, 11], [12, 17], [20, 25], [26, 28]]
b = []
lower_curr = a[0][0]
upper_curr = a[0][1]
for i in range(len(a)-1):
    lower_1 = a[i][0]
    lower_2 = a[i 1][1]

    upper_1 = a[i][1]
    upper_2 = a[i 1][1]

    if upper_1 - lower_2 >= 2:
        b.append((lower_1, upper_1))
    else:
        lower_curr = lower_1
        upper_curr = upper_2

What I am unable to do is to write logic on when to append either lower_1 vs lower_curr. Feel free to write your own logic or fix mine.

CodePudding user response:

I'd consider using a generator for this

from copy import copy
def condense(lst):
    current = copy(lst[0])
    for i, j in zip(lst, lst[1:]):
        if j[0] - i[1] > 1:
            yield copy(current)
            current = j
        else:
            current[1] = j[-1]
    yield copy(current)

a = [[0, 1], [3, 4], [5, 11], [12, 17], [20, 25], [26, 28]]
list(condense(a)) 

gives

[[0, 1], [3, 17], [20, 28]]

CodePudding user response:

The simplest approach would be the brute-force approach to the solution.
In my approach, I have initialized the variables along with a changes variable. I have made changes to a copy of the list.
The algorithm is as follows:

  1. Cycle through the list from indexes 0 to len(a)-1 in order to prevent array index out of bounds error.
  2. At each step check whether the difference between the last element at the current index and 1st element of the next index is less than 2
  3. If yes, the changes are made to the copy of the list. The changes include setting the last element of the current index to the last element of the next index and popping out the next index.
  4. The changes variable is used to update the index value such that it brings the changes to the next element each time.

The Code:

a = [[0, 1], [5, 6], [7, 11], [11, 21], [27, 29], [30, 38], [39, 41], [43, 50], [52, 52], [55, 56]] #The main list
b = a[:]
changes = 0
i = 0
while i < len(a)-1:
    if a[i 1][0] - a[i][1] < 2:
        b[i-changes][1] = b[i-changes 1][1] # Change the 2nd elemnent of the 
                                            # element at the current index.
        b = b[:i 1-changes]   b[i 2-changes:] # Removing the next element(I prefer 
                                              # it this way)
        changes  = 1 # Updating the changes value every time an element is popped
    i = 1
print(b)

CodePudding user response:

just edit your code slightly, you don't need to track that much of variables, only the current lower limit, that is updated whenever you append to the list, and the upper bound that is always updated, because this will increase on each iteration.

and you just have to append whenever the condition is violated, and also append the last result, because the last element cannot violate any condition.

a = [[0, 1], [3, 4], [5, 11], [12, 17], [20, 25], [26, 28]]
b = []
lower_curr = a[0][0]
upper_curr = a[0][1]
for i in range(1,len(a)):
    lower_2 = a[i][0]
    upper_2 = a[i][1]

    if lower_2 - upper_curr >= 2:
        b.append([lower_curr,upper_curr])
        lower_curr = lower_2
    upper_curr = upper_2
    
b.append([lower_curr,upper_curr])
print(b)
  • Related