在 Python 中过滤数组中的 Anagram

Filter Anagram in Array in Python

我正在尝试遍历数组并删除 python 中不是字谜的元素。这是我写的代码。我的逻辑似乎很好,但我似乎无法理解。

b = ['cat', 'dog', 'god', 'star', 'lap', 'act']
array=[]
t=0
for i in b:
    while t<len(b):
        if ''.join(sorted(i))==''.join(sorted(b[t])):
           array.append(i)
        t+=1
print array

你的程序中的第一个问题是你在 for 循环之外将 t 初始化为 0,因此你只检查 b 的第一个元素和所有元素,对于 for 循环的其余迭代,t 将始终大于 len(b) ,因此它永远不会进入内部循环,从 for 循环的第二次迭代开始。一个简单的修复 -

for i in b:
    t = 0
    while t<len(b):
        if ''.join(sorted(i))==''.join(sorted(b[t])):
           array.append(i)
        t+=1

但是对于找字谜,我觉得你把它复杂化了,你可以简单地找出字符串字符的ASCII值的总和,然后将它与其他相同的总和和长度进行比较,并检查两者是否ASCII 值和字符串长度的总和匹配,如果匹配则为变位词。

此方法的示例代码 -

b = ['cat', 'dog', 'god', 'star', 'lap', 'act']
c = list(map(len,b))
d = list(map(lambda x: sum([ord(c) for c in x]), b))
arr= []
for i, s in enumerate(b):
    for j, s1 in enumerate(b):
            if d[i] == d[j] and c[i] == c[j] and i != j:
                    if s not in arr:
                            arr.append(s)
                    if s1 not in arr:
                            arr.append(s1)
print(arr)
>> ['cat', 'act', 'dog', 'god']

另一种方法

使用 itertools groupby

In [18]: from itertools import groupby


In [19]: c=[list(g) for k,g in groupby(sorted(b,key=sorted),sorted)]

In [20]: c
Out[20]: [['cat', 'act'], ['lap'], ['star'], ['dog', 'god']]

In [21]: [x for _list in c if len(_list)>1 for x in _list]
Out[21]: ['cat', 'act', 'dog', 'god']

The key thing here is to use itertools.groupby from the itertools module which will group items in a list together.

The list we supply to groupby has to be sorted in advanced so we pass it sorted(b,key=sorted). The trick here is that sorted can take a key function and will sort based on the output from this function, so we pass sorted again as the key function and this will will sort the words using the letters of the string in order. There's no need to define our own function or create a lambda.

groupby takes a key function which it uses to tell if items should be grouped together and again we can just pass it the built-in sorted function.

来源:Finding and grouping anagrams by Python

实际上您的解决方案是错误的,使用 2 for 循环的想法效率不高。你正在迭代你的列表 2 次并在你的元素上应用 ''.join(sorted()) 2 次你也在将每个元素与自身进行比较!相反,您可以使用字典通过遍历列表的 enumerate 来获取字谜元素的索引:

>>> d={}
>>> for i,j in enumerate(b):
...   d.setdefault(''.join(sorted(j)),[]).append(i)
... 
>>> d
{'arst': [3], 'dgo': [1, 2], 'alp': [4], 'act': [0, 5]}

>>> [b[t] for k in d.values() if len(k)>1 for t in k]
['dog', 'god', 'cat', 'act']

如果您关心顺序,您可以使用 collections 模块中的 OrderedDict 函数:

>>> from collections import OrderedDict
>>> d=OrderedDict()
>>> for i,j in enumerate(b):
...   d.setdefault(''.join(sorted(j)),[]).append(i)
... 
>>> [b[t] for k in d.values() if len(k)>1 for t in k]
['cat', 'act', 'dog', 'god']

只需对现有代码进行一些小的调整即可。

b = ['cat', 'dog', 'god', 'star', 'lap', 'act']
array = []
t = 0
for i, value in enumerate(b):
    t = i+1
    while t<len(b):
        if ''.join(sorted(value))==''.join(sorted(b[t])):
            array.extend([value, b[t]])
        t+=1
print array
['cat', 'act', 'dog', 'god']