所以我有一个有趣的问题。
我正在尝试写一些单词混乱,我需要知道我使用了哪些字母,哪些字母没有。到目前为止,我有以下代码:
def remove_common(x,y):
sort = sort = lambda x: "".join(c for c in sorted(x.lower()) if c.isalpha())
x,y = sort(x), sort(y)
//some code that removes y from x
return leftovers
print remove_common("Lets chat about code","that cool cat")
print remove_common("A silly word","a lil sword")
print remove_common("The Thing","Height")
>>> "bdeesu"
>>> "iy"
>>> "tn"
我正在寻找一种简单的方法来删除两者中的字母,但在必要时留下重复的内容。
x = "aa"
和y = "a"
,则结果为"a"
,而不是""
。我认为这排除了套装的使用。sorted()
。我已经查看了其他答案,但这些答案主要与仅提供未出现在一个字母中的字母有关并删除重复字段。
答案 0 :(得分:7)
您可以使用collections.Counter
个对象,这些对象可以相互减去:
import collections
def remove_common(x,y):
count = lambda x: collections.Counter(c for c in x.lower() if c.isalpha())
cx, cy = count(x), count(y)
diff = cx - cy
rev_diff = cy - cx
assert len(rev_diff) == 0, "%s in y and not x" % "".join(rev_diff.elements())
return "".join(sorted(diff.elements()))
作为正在发生的事情的演示:
>>> c1 = collections.Counter("hello world")
>>> c2 = collections.Counter("hey worlds")
>>> c1 - c2
Counter({'l': 2, 'o': 1})
>> (c1 - c2).elements()
['l', 'l', 'o']
答案 1 :(得分:1)
collections.Counter
运算符, -
将不会让任何计数低于零。但是,如果您使用c.subtract(d),那么它将允许您这样做。此外,使用c.elements()时,将忽略具有负计数的值。
这是一个基于collections.Counter:
的实现import collections
def remove_common(x, y):
sort = lambda x: "".join(c for c in sorted(x.lower()) if c.isalpha())
x, y = list(sort(x)), list(sort(y))
cx = collections.Counter(x)
cy = collections.Counter(y)
cx.subtract(cy)
result = ""
for letter, count in cx.iteritems():
for i in range(abs(count)):
result += letter
return result
我在以下测试集上运行它:
print remove_common("Lets chat about code","that cave")
print remove_common("basdf aa", "a basd")
print remove_common("asdfq", "asdf")
print remove_common("asdf", "asdfq")
print remove_common("aa bb s", "a bbb")
结果:
cbedloosutv
af
q
q
asb
要检测y中但不是x中的字母,您应该将cy.subtract(cx)
的结果与cy
的值进行比较。例如:
cz = collections.Counter(cy) # because c.subtract(..) modifies c
cz.subtract(cx)
for letter, count in cz.iteritems():
if count == cy[letter]: # in the case that there were none of letter in x
assert False
如果y中存在一个字母但是重复的次数比x中的更多次,我看到的其他解决方案也失败了(例如:'hi there'和'hii'会在Josh Smeaton的解决方案中产生AssertionError但不是这个)。在这方面你的要求有点模糊IMO。 stackoverflow的美妙之处在于,有足够的答案来挑选你的毒药。
希望这有帮助。
答案 2 :(得分:1)
以David Robinsons的回答为基础:
import collections.Counter as C
def remove_common(x,y):
s1,s2=filter(str.isalpha, x.lower()),filter(str.isalpha, y.lower())
c1,c2 = C(s1),C(s2)
if any(c2-c1):
assert False
return list((c1-c2).elements())
>>> remove_common('hi there','hi')
['h', 'r', 'e', 'e', 't']
>>> x,y='Lets chat about code','that cool cat'
>>> remove_common(x,y)
['u', 's', 'b', 'e', 'e', 'd']
>>> remove_common('hi','ho')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in remove_common
AssertionError