Elegant Find Sub-List in List

elegant find sub-list in list

I know this question is 5 months old and already "accepted", but googling a very similar problem brought me to this question and all the answers seem to have a couple of rather significant problems, plus I'm bored and want to try my hand at a SO answer, so I'm just going to rattle off what I've found.

The first part of the question, as I understand it, is pretty trivial: just return the original list with all the elements not in the "pattern" filtered out. Following that thinking, the first code I thought of used the filter() function:

def subfinder(mylist, pattern):
return list(filter(lambda x: x in pattern, mylist))

I would say that this solution is definitely more succinct than the original solution, but it's not any faster, or at least not appreciably, and I try to avoid lambda expressions if there's not a very good reason for using them. In fact, the best solution I could come up with involved a simple list comprehension:

def subfinder(mylist, pattern):
pattern = set(pattern)
return [x for x in mylist if x in pattern]

This solution is both more elegant and significantly faster than the original: the comprehension is about 120% faster than the original, while casting the pattern into a set first bumps that up to a whopping 320% faster in my tests.

Now for the bonus: I'll just jump right into it, my solution is as follows:

def subfinder(mylist, pattern):
matches = []
for i in range(len(mylist)):
if mylist[i] == pattern[0] and mylist[i:i+len(pattern)] == pattern:
matches.append(pattern)
return matches

This is a variation of Steven Rumbalski's "inefficient one liner", that, with the addition of the "mylist[i] == pattern[0]" check and thanks to python's short-circuit evaluation, is significantly faster than both the original statement and the itertools version (and every other offered solution as far as I can tell) and it even supports overlapping patterns. So there you go.

Is there an elegant way to find an item in a list of list with multiple layers in python

If you don't want to flatten the array, you can use recursion to iterate over a list and recurs on each another list inside it.

Code:

def check(lst, x):
for i in range(len(lst)):
if type(lst[i]) == list: # If there is another list inside it
if check(lst[i], x): # If the value x exist in lst[i]
return True
elif lst[i] == x: # If there is no more list inside it
return True
return False # X can't be found in lst.

print(check([0, [1, [2, [3]]], [4, [5]], 6], 5)) # Output: True
print(check([0, [1, [2, [3]]], [4, [5]], 6], 9)) # Output: False

Find the position of sublist in a list in python

x = [0,1,2,3,4,5,6,7]
y = [3,4,5]

occ = [i for i, a in enumerate(x) if a == y[0]]

for b in occ:
if x[b:b+len(y)] == y:
print 'YES-- SUBLIST at : ', b
break
if len(occ)-1 == occ.index(b):
print 'NO SUBLIST'
break

What's an elegant way to extract a series of entries in a list of tuples into sublists?

You can use tuple() function to transform lists into tuples, so you will be able to append all of the tuples inside listOfTuples variable into the output that you need:

TRUE = 1
lot = [('selectable', 'frequency'), ('color', 'green'), ('item', '10 Hz'),
('value', 10), ('align', 'left'), ('hidden', TRUE), ('item', '20 Hz'),
('value', 20), ('align', 'right'), ('item', '50 Hz'), ('value', 50),
('item', '100 Hz'), ('value', 100), ('textColor', 0xFF0000)]

l = [[]]
for i in lot:
if i[0]=='item':
l[-1] = tuple(l[-1])
l.append([])
l[-1].append(i)
print(l[1:])

Output:

[(('item', '10 Hz'), ('value', 10), ('align', 'left'), ('hidden', 1)), (('item', '20 Hz'), ('value', 20), ('align', 'right')), (('item', '50 Hz'), ('value', 50)), [('item', '100 Hz'), ('value', 100), ('textColor', 16711680)]]

The only disadvantage of this method is that you need to remove the first element of the output list of tuples, so it may doesn't work in certain situations.

My code works but need an elegant way to produce sub-lists out of a list

You can just write a list comprehension to achieve the result you want:

lst = [0, 10]
slotss = 4

out_lst = [[start, start + (slotss - 1)] for start in range(lst[0], lst[1] - (slotss - 1))]

Output:

[[0, 3], [1, 4], [2, 5], [3, 6], [4, 7], [5, 8], [6, 9]]

Most programmatically elegant (pythonic) way to take ith element of list of lists of lists, and create lists of these ith elements

Your original code isn't bad at all. These existing answers are great, but I think

result = []

for item in lll:
result.extend(zip(*item))

is reasonably succinct and Pythonic, arguably more readable than a one-liner, no imports and worth consideration. extend is a common refactor for append + loop for flattening lists and zip is almost always the way to go for columnwise iteration and matrix rotation.

If you need lists instead of tuples:

result = []

for item in lll:
result.extend([list(x) for x in zip(*item)])

or with map:

for item in lll:
result.extend(map(list, zip(*item)))

A couple of minor style suggestions courtesy of PEP-8:

  • snake_case is preferred over camelCase.
  • Avoid l as a variable name. It's too easily confused for i and 1.

Also, num_things = len(item[0]) strikes me as a bit dangerous because it'll raise an IndexError if item is empty.

Finding all list and sublist combination from flat list

Question is quite vague, I think what you are looking for is set-partitions:

def partition(collection):
if len(collection) == 1:
yield [ collection ]
return

first = collection[0]
for smaller in partition(collection[1:]):
# insert `first` in each of the subpartition's subsets
for n, subset in enumerate(smaller):
yield smaller[:n] + [[ first ] + subset] + smaller[n+1:]
# put `first` in its own subset
yield [ [ first ] ] + smaller

something = ['a', 'b', 'c']

for n, p in enumerate(partition(something), 1):
print(n, sorted(p))

Output:

1 [['a', 'b', 'c']]
2 [['a'], ['b', 'c']]
3 [['a', 'b'], ['c']]
4 [['a', 'c'], ['b']]
5 [['a'], ['b'], ['c']]

Get information out of sub-lists in main list elegantly

I think you can certainly make your code more concise and easier to read by using defaultdict to create a dictionary from the first two elements in each sublist to all the third items:

from collections import defaultdict
nums = defaultdict(list)
for arr in a:
key = tuple(arr[:2]) # make the first two floats the key
nums[key].append( arr[2] ) # append the third float for the given key

a_processed = [[k[0], k[1], sum(vals)/len(vals)] for k, vals in nums.items()]

Using this, I get the same output as you (albeit in a different order):

[[0.2, 1.1, 0.8], [1.2, 0.3, 0.6], [0.3, 1.4, 0.2], [0.6, 0.4, 0.9], [1.1, 0.5, 0.6666666666666666], [0.6, 0.2, 0.75]]

If the order of a_processed is an issue, you can use an OrderedDict, as pointed out by @DSM.

What is the most elegant way of finding the n-length consecutive sub-lists of a list in Python?

>>> some_lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l = [some_lst[i:i+3] for i in xrange(len(some_lst)-2)]


Related Topics



Leave a reply



Submit