python-3.xlistreview

Divide a list according to another's lists indices


I have written a script that takes the following list:

route = [51, 5, 33, 39, 34, 32, 64, 53, 62, 66, 58, 59, 54, 38, 9, 21, 29, 2, 61, 11, 50, 16, 20, 28, 31, 8, 26, 43, 7, 1, 27, 60, 55, 52, 10, 30, 49, 46, 12, 15, 44, 45, 37, 56, 65, 63, 42, 19, 40, 41, 13, 25, 14, 18, 57, 48, 23, 24, 6, 3, 36, 35, 22, 17, 4, 47]

and divides it into smaller lists according to where the items in this list are:

globalDepots = [i for i in range(50, 66)]

In short, it takes the next depot's index and make a miniRoute out of it. The result should be:

Total number of valid miniRoutes is 16
All mini routes: 
#1   [51, 5, 33, 39, 34, 32, 64]
#2   [64, 53]
#3   [53, 62]
#4   [62, 66, 58]
#5   [58, 59]
#6   [59, 54]
#7   [54, 38, 9, 21, 29, 2, 61]
#8   [61, 11, 50]
#9   [50, 16, 20, 28, 31, 8, 26, 43, 7, 1, 27, 60]
#10  [60, 55]
#11  [55, 52]
#12  [52, 10, 30, 49, 46, 12, 15, 44, 45, 37, 56]
#13  [56, 65]
#14  [65, 63]
#15  [63, 42, 19, 40, 41, 13, 25, 14, 18, 57]
#16  [57, 48, 23, 24, 6, 3, 36, 35, 22, 17, 4, 47, 50]

My script below gets the results shown above, but I was hoping someone could show me a nicer way to achieve the same result.

import random

def countMiniRoutes(route):
    depotIndexes = []
    for depot in globalDepots:
        index = route.index(depot)
        depotIndexes.append(index)
    miniRoutesList = []
    sortedDepotIndexes = sorted(depotIndexes)
    start = sortedDepotIndexes[0]
    if route[-1] not in globalDepots:
        route.append(globalDepots[0])

    for i, depotIndex in enumerate(sortedDepotIndexes):
        try:
            stop = sortedDepotIndexes[i+1]+1
        except IndexError:
            stop = len(route)
        miniRoute = route[start:stop]
        try:
            dist = random.random()
            miniRoutesList.append(miniRoute)
        except ZeroDivisionError:
            # if dist == 0, then do not add it to miniRoutesList
            continue
        try:    
            start = sortedDepotIndexes[i+1]
        except IndexError:
            start = sortedDepotIndexes[i]
            
    print(f"Total number of valid miniRoutes is {len(miniRoutesList)}")
    print("All mini routes: ")
    for i, route in enumerate(miniRoutesList):
        print(f"#{i+1} \t {route}")

if __name__ == "__main__":
    globalDepots = [i for i in range(50, 66)]
    route = [51, 5, 33, 39, 34, 32, 64, 53, 62, 66, 58, 59, 54, 38, 9, 21, 29, 2, 61, 11, 50, 16, 20, 28, 31, 8, 26, 43, 7, 1, 27, 60, 55, 52, 10, 30, 49, 46, 12, 15, 44, 45, 37, 56, 65, 63, 42, 19, 40, 41, 13, 25, 14, 18, 57, 48, 23, 24, 6, 3, 36, 35, 22, 17, 4, 47]
    countMiniRoutes(route)

Solution

  • IIUC you want to extract segments of routethat start and end with an element of globalDepots. First I would make a set of globalDepots. I don't understand what you're doing with random. It doesn't seem necessary to solve the problem. Then just iterate over route while keeping track of the index:

    route = [51, 5, 33, 39, 34, 32, 64, 53, 62, 66, 58, 59, 54, 38, 9, 21, 29, 2, 61, 11, 50, 16, 20, 28, 31, 8, 26, 43, 7, 1, 27, 60, 55, 52, 10, 30, 49, 46, 12, 15, 44, 45, 37, 56, 65, 63, 42, 19, 40, 41, 13, 25, 14, 18, 57, 48, 23, 24, 6, 3, 36, 35, 22, 17, 4, 47]
    globalDepots_list = [i for i in range(50, 66)]
    globalDepots_set = set(globalDepots_list)
    
    miniRoutesList = []
    current_d = 0
    for i, d in enumerate(route[1:], 1):
        if d in globalDepots_set:
            miniRoutesList.append(route[current_d:i+1])
            current_d = i
        elif i==len(route)-1:
            miniRoutesList.append(route[current_d:] + [globalDepots_list[0]])
    
    print(f"Total number of valid miniRoutes is {len(miniRoutesList)}")
    print("All mini routes: ")
    for i, route in enumerate(miniRoutesList):
        print(f"#{i+1} \t {route}")
    

    Output:

    Total number of valid miniRoutes is 16
    All mini routes: 
    #1       [51, 5, 33, 39, 34, 32, 64]
    #2       [64, 53]
    #3       [53, 62]
    #4       [62, 66, 58]
    #5       [58, 59]
    #6       [59, 54]
    #7       [54, 38, 9, 21, 29, 2, 61]
    #8       [61, 11, 50]
    #9       [50, 16, 20, 28, 31, 8, 26, 43, 7, 1, 27, 60]
    #10      [60, 55]
    #11      [55, 52]
    #12      [52, 10, 30, 49, 46, 12, 15, 44, 45, 37, 56]
    #13      [56, 65]
    #14      [65, 63]
    #15      [63, 42, 19, 40, 41, 13, 25, 14, 18, 57]
    #16      [57, 48, 23, 24, 6, 3, 36, 35, 22, 17, 4, 47, 50]
    

    Edit: appending the first global depot when the last element of route isn't a global depot. Also printing only after computing miniRoutesList to match your code.