Problem mit List Comprehension - Wörter mit gleichem Anfang

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
georgebaker
User
Beiträge: 25
Registriert: Freitag 12. April 2013, 19:53

Hallo,

Ich mache gerade einen Onlinekurs (Linear Algebra through Computer Science Applications) und eine der Aufgaben für diese Woche lautet einen Inverse Index mit Hilfe von List Comprehensions zu schreiben. Bis auf ein kleines Problem funktioniert mein Code auch, ich weiß auch wo der Fehler steckt, aber ich probiere schon seit zwei Tagen ihn zu beheben, aber nichts will klappen. Verwendet wird Python 3.3.2

Code: Alles auswählen

def makeInverseIndex(strlist):
    wordlist = [x for line in strlist for x in line.split()]
    return {word:set{x for (x,y) in enumerate(strlist) if word in strlist[x]} for word in wordlist}
Hier der Output:

Code: Alles auswählen

>>> s = ['this is the first document',
     'this is the second document',
     'and this is a third document',
     'perhaps there should be a fourth document',
     'and now there is a fifth too']
>>> makeInverseIndex(s)
{'and': {2, 4}, 'a': {2, 3, 4}, 'now': {4}, 'third': {2}, 'be': {3}, 'this': {0, 1, 2}, 'is': {0, 1, 2, 4}, 'there': {3, 4}, 'should': {3}, 'perhaps': {3}, 'second': {1}, 'too': {4}, 'fourth': {3}, 'the': {0, 1, 3, 4}, 'document': {0, 1, 2, 3}, 'fifth': {4}, 'first': {0}}
Genau so lautet auch die Aufgabenstellung, aber das Problem tritt auf sobald Wörter gleich beginnen.
z.B.:

Code: Alles auswählen

>>> s = ['dog', 'cat', 'dogs', 'cats']
>>> makeInverseIndex(s)
{'dogs': {2}, 'cats': {3}, 'dog': {0, 2}, 'cat': {1, 3}}
Es liegt daran das z.B.: 'dog' in 'dogs' True ergibt. Gibt es eine Möglichkeit die List Comprehension umzuschreiben damit das nicht passieren kann? Oder sollte ich nochmal von vorne beginnen? (Es dürfen übrigens keine externen Bibliotheken verwendet werden, nur Build-In-Functions)

Vielen Dank im Vorraus,
Georgebaker
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Code: Alles auswählen

def makeInverseIndex(strlist):
    wordlist = [x for line in strlist for x in line.split()]
    return {word:{x for x, y in enumerate(strlist) if word == y} for word in wordlist}

>>> makeInverseIndex(['dog', 'cat', 'dogs', 'cats'])
{'dogs': {2}, 'cats': {3}, 'dog': {0}, 'cat': {1}}
`'dog' in 'dogs'` ist eben wahr, `'dog' == 'dogs'` aber nicht.
BlackJack

@georgebaker: Der Test ist ja auch falsch. Ein ``word in some_other_word`` sollte gar nicht vorkommen, das ist kein sinnvoller Test im Rahmen dieser Aufgabe.
georgebaker
User
Beiträge: 25
Registriert: Freitag 12. April 2013, 19:53

:oops: Manchmal sieht man den Wald vor lauter Bäumen nicht! :D Vielen Dank
BlackJack

@cofi: Du vergleichst da ganze Dokumente auf Gleichheit mit einzelnen Worten. Das funktioniert nur wenn die Dokumente jeweils nur aus einem Wort bestehen:

Code: Alles auswählen

In [39]: makeInverseIndex(['cat', 'dog', 'dogs', 'cat and dog'])
Out[39]: {'and': set([]), 'cat': set([0]), 'dog': set([1]), 'dogs': set([2])}
Nahezu ungetestet:

Code: Alles auswählen

def main():
    documents = [
        'this is the first document',
        'this is the second document',
        'and this is a third document',
        'perhaps there should be a fourth document',
        'and now there is a fifth too',
    ]
    document_words = [set(d.split()) for d in documents]
    all_words = set(w for words in document_words for w in words)
    print dict(
        (w, [i for (i, ws) in enumerate(document_words) if w in ws])
        for w in all_words
    )


if __name__ == '__main__':
    main()
Wobei das eine nette Fingerübung für LCs/Generatorausdrücken ist, aber von Effizienz und Lesbarkeit ein wenig entfernt ist. ;-)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

BlackJack hat geschrieben:@cofi: Du vergleichst da ganze Dokumente auf Gleichheit mit einzelnen Worten.
Man darf doch nicht die ganze Arbeit erledigen 8)
Antworten