0

我正在构建一个用单词构建字典的函数,例如:

{'b': ['b', 'bi', 'bir', 'birt', 'birth', 'birthd', 'birthda', 'birthday'],
'bi': ['bi', 'bir', 'birt', 'birth', 'birthd', 'birthda', 'birthday'],
'birt': ['birt', 'birth', 'birthd', 'birthda', 'birthday'], 
'birthda': ['birthda', 'birthday'], 
'birthday': ['birthday'], 
'birth': ['birth', 'birthd', 'birthda', 'birthday'],
'birthd': ['birthd', 'birthda', 'birthday'], 
'bir': ['bir', 'birt', 'birth', 'birthd', 'birthda', 'birthday']}

这是它的样子:

def add_prefixs(word, prefix_dict):
    lst=[]
    for letter in word:
        n=word.index(letter)
        if n==0:
            lst.append(word[0])
        else:
            lst.append(word[0:n])
    lst.append(word)
    lst.remove(lst[0])
    for elem in lst:
        b=lst.index(elem)
        prefix_dict[elem]=lst[b:]
    return prefix_dict

它适用于“生日”之类的单词,但是当我有一个重复的字母时,我遇到了问题......例如,“你好”。

{'h': ['h', 'he', 'he', 'hell', 'hello'], 'hell': ['hell', 'hello'], 'hello': ['hello'], 'he': ['he', 'he', 'hell', 'hello']}

我知道这是因为索引(python选择第一次出现字母的索引)但我不知道如何解决它。是的,这是我的作业,我真的很想向你们学习 :)

4

4 回答 4

4

你已经遍历了这个词;而不是使用.index()保持计数器。Python 让这一切变得非常简单;使用enumerate()功能:

for n, letter in enumerate(word):
    if n==0:
        lst.append(word[0])
    else:
        lst.append(word[0:n])

现在您不再使用letter变量,因此只需range(len(word)

for n in range(len(word)):
    if n==0:
        lst.append(word[0])
    else:
        lst.append(word[0:n])

我们可以将其简化为列表推导:

lst = [word[0:max(n, 1)] for n in range(len(word))]

注意max()那里;我们没有测试是否为 0,而是为切片n设置了最小值。1

由于您随后再次删除第一个条目(因为它与第二个结果相同)添加了完整的单词,因此只需将 1 添加到n计数器:

lst = [word[0:n+1] for n in range(len(word))]

您的功能的后半部分可以有效地使用该enumerate()功能,而不是.index()

for b, elem in enumerate(lst):
    prefix_dict[elem]=lst[b:]

现在您的功能要简单得多;请注意,由于您正在就地操作,因此无需返回: prefix_dict

def add_prefixs(word, prefix_dict):
    lst = [word[0:n+1] for n in range(len(word))]
    for b, elem in enumerate(lst):
        prefix_dict[elem]=lst[b:]
于 2012-11-27T16:47:13.930 回答
0

通过考虑索引而不是字母来简化您的解决方案要容易得多。通常在 Python 中,我们循环遍历值,因为这是我们关心的。在这里,我们实际上是为字符串生成前缀,其中内容无关紧要,而是位置重要:

def prefixes(seq):
    for i in range(len(seq)):
        yield seq[:i+1]

segments = list(prefixes("birthday"))
print({segment: segments[start:] for start, segment in enumerate(segments)})

您真正想要的是获取单词的每个前缀,我们可以在极少数情况下执行此操作,即循环遍历索引是一个有效的选项,因为这正是我们正在尝试做的。

然后,我们使用字典理解为每个段选择正确的“子”组。

这给了我们(为了清楚起见,添加了一些空白):

{
    'birt': ['birt', 'birth', 'birthd', 'birthda', 'birthday'], 
    'bir': ['bir', 'birt', 'birth', 'birthd', 'birthda', 'birthday'], 
    'birthday': ['birthday'], 
    'bi': ['bi', 'bir', 'birt', 'birth', 'birthd', 'birthda', 'birthday'], 
    'birthda': ['birthda', 'birthday'], 
    'b': ['b', 'bi', 'bir', 'birt', 'birth', 'birthd', 'birthda', 'birthday'], 
    'birthd': ['birthd', 'birthda', 'birthday'], 
    'birth': ['birth', 'birthd', 'birthda', 'birthday']
}

如果您不介意一些额外的循环,我们甚至可以将其简化为:

def prefixes(word):
    for i in range(len(word)):
        segment = word[:i+1]
        yield segment, [segment[:i+1] for i in range(len(segment))]

print(dict(prefixes("birthday")))

作为旁注,另一个实现prefixes()是:

def prefixes(seq):
    return prefixes(seq[:-1])+[seq] if seq else []

但是,这是一个递归函数,并且由于 Python 没有针对递归进行优化,因此这是一种更糟糕的方法。它还创建了一个列表而不是生成器,这在某些情况下内存效率较低。

于 2012-11-27T16:52:53.053 回答
0

Martijn比我快,但我有一些补充:

def add_prefixs(word, prefix_dict):
    lst=[]
    for n, letter in enumerate(word):
        if n > 0:
            lst.append(word[0:n])
    lst.append(word)
    for elem in lst:
        b=lst.index(elem)
        prefix_dict[elem]=lst[b:]
    return prefix_dict

如果立即删除它,为什么要放置第 0 个条目?

另一个简化可能是

def add_prefixs(word, prefix_dict):
    #lst=[word[0:n] for n, letter in enumerate(word) if n > 0] + [word]
    # why do I think so complicated? Better use
    lst=[word[0:n+1] for n, letter in enumerate(word)]
    prefix_dict.update((elem, lst[b:]) for b, elem in enumerate(lst))
    return prefix_dict

像这样的班级

class Segments(object):
    def __init__(self, string, minlength=1):
        self.string = string
        self.minlength = minlength
    def __getitem__(self, index):
        s = self.string[:self.minlength + index]
        if len(s) < self.minlength + index: raise IndexError
        if index >= len(self): raise IndexError # alternatively
        return s
    def cut(self, num):
        return type(self)(self.string, self.minlength + num)
    def __repr__(self):
        return repr(list(self))
    def __len__(self):
        return len(self.string) - self.minlength + 1

您可以进一步简化:

def add_prefixes(word, prefix_dict):
    lst = Segments(word)
    prefix_dict.update((prefix, lst.cut(n)) for n, prefix in enumerate(lst))
    return prefix_dict

嗯。如果我再想一想,这并不简单。但它避免了本质上相同的数据或部分数据的许多副本......

于 2012-11-27T16:53:54.490 回答
0

我认为最pythonic的方法是:

def add_prefixs(word, prefix_dict):
    lst = [word[0:n+1] for n in range(len(word))]
    prefix_dict.update((k, lst[n:]) for n, k in enumerate(lst))
于 2012-11-27T18:00:25.337 回答