abkds
abkds

Reputation: 1794

Pythonic way of defining the function

A homework assignment asks us to write some functions, namely orSearch and andSearch .

"""
Input: an inverse index, as created by makeInverseIndex, and a list of words to query
Output: the set of document ids that contain _any_ of the specified words
Feel free to use a loop instead of a comprehension.

>>> idx = makeInverseIndex(['Johann Sebastian Bach', 'Johannes Brahms', 'Johann Strauss the Younger', 'Johann Strauss the Elder', ' Johann Christian Bach',  'Carl Philipp Emanuel Bach'])
>>> orSearch(idx, ['Bach','the'])
{0, 2, 3, 4, 5}
>>> orSearch(idx, ['Johann', 'Carl'])
{0, 2, 3, 4, 5}
"""

Given above is the documentation of orSearch similarly in andSearch we return only those set of docs which contains all instances of the query list.

We can assume that the inverse index has already been provided. An example of an inverse index for ['hello world','hello','hello cat','hellolot of cats'] is {'hello': {0, 1, 2}, 'cat': {2}, 'of': {3}, 'world': {0}, 'cats': {3}, 'hellolot': {3}}

So my question is, I was able to write a single line comprehension for the orSearch method given by

def orSearch(inverseIndex, query):
    return {index for word in query if word in inverseIndex.keys() for index in inverseIndex[word]}

But I am unable to think of the most pythonic way of writing andSearch. I have written the following code, it works but I guess it is not that pythonic

def andSearch(inverseIndex, query):
    if len(query) != 0:
        result = inverseIndex[query[0]]
    else:
        result = set()

    for word in query:
        if word in inverseIndex.keys():
            result = result & inverseIndex[word]

    return result

Any suggestions on more compact code for andSearch ?

Upvotes: 0

Views: 128

Answers (2)

Sergey Novopoltsev
Sergey Novopoltsev

Reputation: 511

More Pythonic way to write andSerch() will be:

from functools import reduce
def andSearch(inverseIndex, query):
    return reduce(lambda x, y: x & y, [(inverseIndex[key]) for key in query])

Here we used reduce function to aggregate results of transitional calculations.

Also it may be useful to check if all items of query are in inverseIndex. Then our function will look like

from functools import reduce
def andSearch(inverseIndex, query):
    if set(query) < set(inverseIndex.keys()):
        return reduce(lambda x, y: x & y, [(inverseIndex[key]) for key in query])
    else:
        return False # or what ever is meaningful to return

Upvotes: 1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798536

Rewrite orSearch() to use any() to find any of the terms, and then derive andSearch() by modifying your solution to use all() instead to find all of the terms.

Upvotes: 2

Related Questions