The problem of slicing a list with sublists

59 Views Asked by At

I need to make a slice with the number 74 from the list using indexes (this is the condition of my assignment). But I don't understand what I need to write to get it. Please help.

This is my list:

L = [[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]], 
    [[21, 22, 23, 24, 25, 26, 27, 28, 29, 30], [31, 32, 33, 34, 35, 36, 37, 38, 39, 40]], 
    [[41, 42, 43, 44, 45], [46, [47, 48], 49, 50], [51, 52, 53, 54, 55], [56, 57, 58, 59, 60]], 
    [61, 62, 63, [64, 65, 66, 67, 68, 69, 70, 71], 72, 73, 74, [75, [76, 77, 78], 79], 80], 
    [81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]]

And if I write L[3][6], I get 74.

But by writing L[3[6]::] , I get an error, even though I need a slice starting with the number with that index.

I need to get something like this:

[[74, [75, [76, 77, 78], 79], 80], [81, 82, 83, 84, 85, 86, 
87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]]
2

There are 2 best solutions below

0
Scott Hunter On BEST ANSWER

As @matszwecja says, L[3][6:] gives you the part of the first sub-list you want, and L[4:] is the rest of the original list; combine them to get the result you want.

0
Alain T. On

Unless you only have that specific data to process, approaching this with indexes and subscripts will make things difficult because you would need to limit the solution to a specific depth of nesting. In Python, when you end up manipulating a lot of indexes, it is often a sign that you are missing out on a simpler solution based on iteration.

This filtering (not really slicing) could be achieved with a recursive function that drills down nested lists to get to values and only outputs non-empty lists and values meeting the condition:

def deepFilter(data,condition=lambda n:n>=74):
    if isinstance(data,list):
        filtered = (deepFilter(value,condition) for value in data)
        return [value for value in filtered if value != []]
    else:
        return data if condition(data) else []

output:

print(deepFilter(L))

[[74, [75, [76, 77, 78], 79], 80], [81, 82, 83, 84, 85, 86, 87, 88,
  89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]]

You could also do it without recursion. This example does it "in-place" (modifying the original lists) by building a list of all the subLists and then applying the filter in a bottom-up order (keeping only non-empty lists and values meeting the condition):

def deepFilter(data,condition=lambda n:n>=74):
    lists = [data]
    lists.extend(value for subList in lists 
                       for value in subList if isinstance(value,list))
    for subList in reversed(lists):
        subList[:] = (value for value in subList
                      if value != [] 
                      and (isinstance(value,list) or condition(value)) )

output:

deepFilter(L)
print(L)

[[74, [75, [76, 77, 78], 79], 80], [81, 82, 83, 84, 85, 86, 87, 88,
  89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]]

or this non-recursive variant that outputs new filtered lists (by making copies as it builds the list of sublists:

def deepFilter(data,condition=lambda n:n>=74):
    lists  = [data.copy()]
    for subList in lists:
        subList[:] = (v.copy() if isinstance(v,list) else v for v in subList)
        lists.extend(v for v in subList if isinstance(v,list))
    for subList in reversed(lists):
        subList[:] = (value for value in subList
                      if value != [] 
                      and (isinstance(value,list) or condition(value)) )
    return lists[0]

print(deepFilter(L))

[[74, [75, [76, 77, 78], 79], 80], [81, 82, 83, 84, 85, 86, 87, 88,
  89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]]