I have a piece of code that checks if two strings are anagrams. I would like this to be as pythonic as possible.
def are_two_string_anagram(string1, string2):
if len(string1) != len(string2):
return False
def char_count(string):
char_count = {}
for s in string:
char_count[s] = char_count.get(s, 0) + 1
return char_count
chr_count = char_count(string1)
chr1_count = char_count(string2)
return chr_count == chr1_count
string1 = "mary"
string2 = "yram"
print(are_two_string_anagram(string1, string2))
string1 = "albert"
string2 = "abelrt"
print(are_two_string_anagram(string1, string2))
string1 = "something"
string2 = "anotherus"
print(are_two_string_anagram(string1, string2))
-
\$\begingroup\$ Related: codereview.stackexchange.com/questions/96475/… \$\endgroup\$Curt F.– Curt F.2015年07月15日 03:21:56 +00:00Commented Jul 15, 2015 at 3:21
1 Answer 1
Most python users would just use sorted(string1) == sorted(string2)
. That's \$O(n log n)\,ドル which is not that much worse than your \$O(n)\$ solution.
But the code you've actually written is just a reimplementation of:
collections.Counter(string1) == collections.Counter(string2)
That said, your short-circuit if the lengths mismatch is a good idea no matter which implementation you use.
There are some style issues that jump out with your implementation:
char_count
doesn't have a pressing need to be a nested function, I would put it at top level.- Don't have a local variable named
char_count
inside the same-named function. - Don't cross numbers like
chr_count = char_count(string1);chr1_count = char_count(string2)
. If you need numbered variables, use the same number for all transformed forms also.
For your demonstration code, I would have written:
def test_two_string_anagrams():
assert are_two_string_anagram("mary", "yram")
assert are_two_string_anagram("albert", "abelrt")
assert are_two_string_anagram("something", "anotherus")
Or possibly:
def test_two_string_anagrams():
for s1, s2 in [
("mary", "yram"),
("albert", "abelrt"),
("something", "anotherus"),
]:
assert are_two_string_anagram(s1, s2)
That way it can be run directly with py.test
(and possibly other harnesses, I know the standard unittest
requires wrapping them in a dummy class, but I haven't used any others).
-
\$\begingroup\$ What if I cannot use
collections.Counter
? is my implementation correct? I was asked for a job interview that I can only use basic functions. \$\endgroup\$toy– toy2015年07月15日 03:10:58 +00:00Commented Jul 15, 2015 at 3:10 -
1\$\begingroup\$ @toy Yeah, you've written the same algorithm as
collections.Counter
uses. \$\endgroup\$o11c– o11c2015年07月15日 03:57:02 +00:00Commented Jul 15, 2015 at 3:57 -
\$\begingroup\$
anotherus
should return false. \$\endgroup\$CodesInChaos– CodesInChaos2015年07月15日 08:48:02 +00:00Commented Jul 15, 2015 at 8:48