Skip to content

Instantly share code, notes, and snippets.

@nejdetckenobi
Last active February 27, 2019 08:04
Show Gist options
  • Save nejdetckenobi/e8493d40f7d3d12977bdb87881258c56 to your computer and use it in GitHub Desktop.
Save nejdetckenobi/e8493d40f7d3d12977bdb87881258c56 to your computer and use it in GitHub Desktop.
A search tool with O(n) complexity for finding something with its neighbours. Useful for a file like object.
#!/usr/bin/env python
from argparse import ArgumentParser, FileType
parser = ArgumentParser()
parser.add_argument('string', type=str, help='String to find')
parser.add_argument('file', type=FileType(),
help='File to look in')
parser.add_argument('--neighbourhoodsize', '-ns', type=int, default=0,
help='Neighbourhood size')
parser.add_argument('--nolinenumbers', action='store_true',
help='Line numbers')
parser.add_argument('--mark', action='store_true',
help='Marks the important line.')
args = parser.parse_args()
def find_with_neighbours(iterator, detector, neighbourhood_size=2):
detected_indexes = []
current_queue = []
for index, item in enumerate(iterator):
current_queue.append(item)
if len(current_queue) > 2 * neighbourhood_size + 1:
current_queue.pop(0)
if detector(item):
detected_indexes.append(index + neighbourhood_size)
if index in detected_indexes:
yield current_queue[:], index + neighbourhood_size
last_index = index
for index in range(last_index, last_index + neighbourhood_size + 1):
if index in detected_indexes:
yield current_queue[:], index + len(current_queue) - neighbourhood_size - 1
current_queue.pop(0)
def print_with_neighbours(neigbourhood, last_index=None, detector=None):
if last_index is not None:
first_index = last_index - len(neigbourhood)
index_size = len(str(last_index))
for index, line in enumerate(neigbourhood, start=first_index):
if args.nolinenumbers:
print(line.strip(), end='')
else:
print('{:{}} {}'.format(index, index_size, line.strip()), end='')
if detector is not None and detector(line):
print(' <--')
else:
print('')
print('\n')
if __name__ == '__main__':
detector = lambda x: args.string in x
g = find_with_neighbours(args.file, detector, getattr(args, 'neighbourhoodsize', 2))
for r, i in g:
print_with_neighbours(r, i, detector=detector if args.mark else None)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment