简体   繁体   中英

How can I get next element in for loop

I have a list with a lot of bool values in it and I want to get this pattern: True, True, False, True, True . To do this I think I need to get the next element in a loop while processing my previous element. How can I do it?

Bonus question: Is there a way to increment the position of an element in a list other than i += 1 thing?

I'll have a stab at:

subset = [True, True, False, True, True]
main = [False, True, False, True, True, True, False, True, True, False, True, False, True]

for i, j in  enumerate(xrange(len(subset), len(main) + 1)):
    if main[i:j] == subset:
        print subset, 'is at', i
        break
else:
    print 'not found'

note : this is a bit brute forceish, but okay for one-offs... otherwise, look at tries...

l = len(some_list) - 3
for i, thing in enumerate(some_list):
    if i == l: break
    if thing and some_list[i+1] and not some_list[i+2] and some_list[i+3]:
        bingo(i)

Another untested try:

needle = [True, True, False, True, True]
needle_len = len(needle)
for i in range(len(stack)-needle_len+1):
    if needle == stack[i:i+needle_len]:
        bingo(i)

If I understand the question properly, what you're trying to do is exactly the same thing as str.find , but looking for a sublist within a list instead of a substring within a string.

If so:

def findSubList(l, sub):
  return (''.join('T' if x else 'F' for x in l)
          .find(''.join('T' if x else 'F' for x in sub)))

This may seem hacky, but it makes sense: You want to find a sub-list within a list, both can be trivially converted to strings, and there's already a built-in function to find a sub-string within a string, so why not use it?

It may turn out to be too slow, but really, it's so fast to code this up that it's worth testing it to see if it's too slow for your purposes. (And even if it is too slow, it's probably the convert-to-string part that's slow, and it may be reasonable to just use strings instead of lists of bools in the first place, or convert once at the start before doing 200 searches, or whatever.)

If this is unavoidably too slow, the next thing I'd do is look at the implementation of str.find and convert it to a generic sequence find. You've got the source to Python, so this shouldn't be too hard. However, it is possible that str.find is in C, which might be painful to port. In that case, you still might want to search for a pure Python str.find online… but let's assume you don't find one.

The next step is to see if there's a sequence find module on PyPI.

If not, there are a handful of well-known algorithms that are either easy to implement, or have free implementations at places like ActiveState or even Wikipedia. See String searching algorithm at Wikipedia for a list, and some comparisons. (The performance characteristics depend on factors that you haven't given us—how many searches you need to do; whether main, subset, or both vary; etc., which means nobody can guess which one will be best without more information.)

It's possible that even the standard string search algorithms aren't fast enough, and there are major efficiency gains to be had by taking advantage of the fact that you're searching single bits instead of 8-bit characters. (If the pattern is fixed, you should even be able to describe the search as a finite state machine and turn that into a hard-coded, provably optimal implementation…)

So, you may have to design something yourself. But it's very unlikely that you will, and I would avoid doing so if at all possible. Whenever you've got a problem this obviously common, it's worth assuming that it's a solved problem and looking for solutions, rather than trying to solve it from first principles.

Fairly efficient, uses a sliding window approach, should run in linear time.

def find_x_in_y(subset, main):
    """ Returns a list of the indexes of the first value of matches. """
    results = []
    for i in xrange(len(main)):
        if main[i:i+5] == subset:
              results.append(i)
    return results

# values borrowed from @JonClements
subset = [True, True, False, True, True]
main = [False, True, False, True, True, True, False, True, True, False, True, False, True]

>>> find_x_in_y(subset, main)
... [4]

@abarnert Fine, here's an actually extremely efficient approach.

Extremely efficient, transforms the entire bool list to a bitarray and runs the native search method.

from bitarray import bitarray

def find_x_in_y(subset, main):
    subarray = bitarray(subset)
    mainarray = bitarray(main)
    return [int(i) for i in mainarray.itersearch(subarray)]

timeit results:

Length of main:                     10      100     1000    10000   100000   1000000

returning _all_ matches:
# number of matches                  1       10      100     1000    10000    100000
# sliding window approach     (0.00059, 0.00502, 0.04194, 0.26211, 2.55554, 26.21962)
# bitarray approach           (0.00028, 0.00072, 0.00484, 0.02926, 0.2822,   2.93676)

returning first match:
# sliding window approach     (0.00034, 0.00034, 0.00034, 0.00021, 0.00026,  0.00059)
# bitarray approach           (0.00017, 0.00017, 0.00016, 0.00011, 0.00014,  0.00049)
# joined string approach      (0.00134, 0.00721, 0.06244, 0.39224, 4.21628, 39.63207)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM