尝试将具有两个序列的嵌套循环转换为lambda

时间:2014-12-10 14:55:27

标签: python lambda

我有这个功能可以检查第一个序列中的所有单词, 如果它们以第二个序列中的一个单词结尾,则删除该结束子字符串。

我试图在一个简单的lambda函数中实现所有这一切,该函数应该进入流水线处理,并且无法找到一种方法。

如果你能帮助我,我将不胜感激:

str_test = ("Thiship is a test string testing slowly i'm helpless")
stem_rules = ('less', 'ship', 'ing', 'es', 'ly','s')

str_test2 = str_test.split()

for i in str_test2:
    for j in stem_rules:
        if(i.endswith(j)):
            str_test2[str_test2.index(i)] = i[:-len(j)]
            break

3 个答案:

答案 0 :(得分:3)

这是一个激活(简单?)lambda的单线程。

(lambda words, rules: sum([[word[:-len(rule)]] if word.endswith(rule) else [] for word in words for rule in rules], []))(str_test.split(), stem_rules)

目前尚不清楚它是如何运作的,这样做并不好。

它通常做的是创建一个列表,其中包含一个匹配的字符串,或一个空缺列表,然后将所有内容聚合到单个列表中,仅包含匹配项。

目前它会在每次匹配时输出,而不仅仅是最长匹配或类似的东西,但是一旦你弄清楚它是如何工作的,也许你可以选择最短的匹配输入中每个单词的匹配列表。

愿上帝与你同在。

答案 1 :(得分:1)

我要做的第一件事就是抛出你的i.endswith(j) for j in stem_rules并使其成为匹配并捕获前缀字符串并匹配(但不会捕获)任何后缀的正则表达式

import re

match_end = re.compile("(.*?)(?:" + "|".join(".*?" + stem + "$" for stem in stem_rules) + ")")
# This is the same as:

re.compile(r"""
    (.*?)          # Capturing group matching the prefix
    (?:            # Begins a non-capturing group...
        stem1$|
        stem2$|
        stem3$     # ...which matches an alternation of the stems, asserting end of string
    )              # ends the non-capturing group""", re.X)

然后,您可以使用该正则表达式对列表中的每个项目进行分项。

f = lambda word: match_end.sub(r"\1", word)

使用包含在列表推导中的内容,你应该得到你的结果

words = [f(word) for word in str_test.split()]
# or map(f, str_test.split())

答案 2 :(得分:0)

要将当前代码转换为单个lambda,管道中的每个步骤都需要以非常实用的方式运行:接收一些数据,然后发出一些数据。你需要避免任何偏离这种范式的东西 - 特别是使用像break这样的东西。这是以这种方式重写步骤的一种方法:

text   = ("Thiship is a test string testing slowly i'm helpless")
stems  = ('less', 'ship', 'ing', 'es', 'ly','s')

# The steps:
#   - get words from the text
#   - pair each word with its matching stems
#   - create a list of cleaned words (stems removed)
#   - make the new text
words  = text.split()
wstems = [ (w, [s for s in stems if w.endswith(s)]) for w in words ]
cwords = [ w[0:-len(ss[0])] if ss else w for w, ss in wstems ]
text2  = ' '.join(cwords)
print text2

掌握这些部件后,可以使用普通替换创建单个lambda。这是怪物:

f = lambda txt: [
    w[0:-len(ss[0])] if ss else w
    for w, ss in [ (w, [s for s in stems if w.endswith(s)]) for w in txt.split() ]
]
text3 = ' '.join(f(text))
print text3

我不确定您是否希望lambda返回新单词或新文本 - 根据需要进行调整。