我正试图用以下代码替换字符串中的重复单词:
from functools import reduce
from collections import Counter
import re
if __name__ == '__main__':
sentence = 'User Key Account Department Account Start Date'
result = reduce(
lambda sentence, word: re.sub(rf'{word}s*', '', sentence, count=1),
filter(lambda x: x[0] if x[1] > 1 else '',
Counter(sentence.split()).items()),
sentence
)
import pdb
pdb.set_trace()
print(result)
# User Key Department Account Start Date
但它并没有打印出预期的内容。奇怪的部分在filter
中。如果我只列出筛选的结果:
[el for el in filter(lambda x: x[0] if x[1] > 1 else '', Counter(sentence.split()).items())]
# [('Account', 2)]
不管lambda中指定了什么,x[0]
。
如果我将一个非false值传递给else子句:
[el for el in filter(lambda x: x[0] if x[1] > 1 else ['foo'], Counter(sentence.split()).items())]
# [('User', 1), ('Key', 1), ('Account', 2), ('Department', 1), ('Start', 1), ('Date', 1)]
我在这里缺少什么?
我想做以下事情:
[el for el in filter(lambda key,value: key if value > 1 else '', Counter(sentence.split()).items())]
得到Account
。但它提高了*** TypeError: <lambda>() missing 1 required positional argument: 'value'
使用列表理解可以很好地工作:
[key for key, value in Counter(sentence.split()).items() if value > 1]
# ['Account']
这里的问题是我不确定你在这里想做什么。但我会解释实际发生了什么。
考虑表达式filter(lambda x: x[0] if x[1] > 1 else '', Counter(sentence.split()).items())
。
filter
的第一个自变量是谓词。这是一个接受一个输入(x
(并返回一个被解释为布尔值的函数。
在这种情况下,让我们考虑谓词lambda x : x[0] if x[1] > 1 else ''
——为了简写,我们将其写成P
。我们将假设我们在有序对(a, b)
上调用此函数,使得a
是字符串,b
是数字。
然后我们看到P((a, b)) = a if b > 1 else ''
。
因此,如果b > 1
,则P((a, b))
计算为a
。该值随后被解释为布尔值(即使它是字符串(,因为P
充当谓词。
当我们解读一些";容器";数据类型,如字符串作为布尔值,我们将容器解释为";真像";如果它是非空的;假样";如果它是空的。因此,在这种情况下,当a
为非空时,a
将被解释为True
,而当a
为空时,则False
。
另一方面,当b <= 1
时,P((a, b))
将计算为''
,然后将其解释为False
(因为它是空字符串(。
所以P((a, b))
是一个字符串,当被解释为布尔值时,它等于b > 1 and (a is non-empty)
。
因此,当我们调用filter(P, seq)
时,其中seq
是对(a, b)
的序列,a
是字符串,b
是数字,我们可以看到,我们将保留b > 1
和a
不为空的对(a, b)
。
事实就是这样。
然而,似乎你想要的是只保留多次出现的项目,而忽略它们的计数。为此,您需要map
和filter
的组合。你会想要
map(lambda x: x[0], filter(lambda x: x[1] > 1, Counter(sentence.split()).items()))
这首先只保留对CCD_ 39,其中CCD_。然后它取下每个剩余的对CCD_ 41并且只保留CCD_。