简体   繁体   中英

Python: Converting a list of sets to a set

I am working on a programming project involving DFAs, and I've come across an error I can't seem to figure out how to bypass.

In this section of code:

from DFA import *

def DAWG():
    alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
                'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
                'y', 'z']
    f = open('lexicontest.txt', 'r')
    dictionary = list(f)
    accepts = []
    for i in dictionary:
        if len(i) >= 3:
            accepts.append(i)
    D = from_word_list(accepts, alphabet)
    newStates = frozenset(D.mn_classes())

I get this error:

Traceback (most recent call last):
 File "...\DAWG.py", line 31, in <module>
DAWG()
  File "...\DAWG.py", line 19, in DAWG
newStates = frozenset(D.mn_classes())
TypeError: unhashable type: 'set'

This is because the method mn_classes() returns a list whose elements are sets. I am looking for a way to convert this list into a set, but I cannot do so right now because sets must be hashable. If anyone could give me advice on how to convert this list into a set, it would be greatly appreciated.

I am using a DFA library designed by Andrew Badr found here and here . This is the code for the method mn_classes():

def mn_classes(self):
    """Returns a partition of self.states into Myhill-Nerode equivalence classes."""
    changed = True
    classes = []
    if self.accepts != []:
        classes.append(self.accepts)
    #nonaccepts = filter(lambda x: x not in self.accepts, self.states)
    nonaccepts = [x for x in self.states if x not in self.accepts]
    if nonaccepts != []:
        classes.append(str(nonaccepts))
    while changed:
        changed = False
        for cl in classes:
            local_change = False
            for alpha in self.alphabet:
                next_class = None
                new_class = []
                for state in cl:
                    next = self.delta(state, alpha)
                    if next_class == None:
                        for c in classes:
                            if next in c:
                                next_class = c
                    elif next not in next_class:
                        new_class.append(state)
                        changed = True
                        local_change = True
                if local_change == True:
                    old_class = []
                    for c in cl:
                        if c not in new_class:
                            old_class.append(c)
                    classes.remove(cl)
                    classes.append(old_class)
                    classes.append(new_class)
                    break
    return classes

Your mn_class code looks suspicious to me, especially classes.append(str(nonaccepts)) seems not to be a set in a list. Followint part is also dubious:

if next_class == None:
    for c in classes:
        if next in c:
            next_class = c

Answering the quesition your asked, "If anyone could give me advice on how to convert this list into a set" modulo "mn_classes() returns a list whose elements are sets" you can use DAWG approach, ie return list of frozensets in mn_classes :

return map(frosenset, classes)

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