在Python中过滤数组中的Anagram

时间:2015-06-20 06:45:25

标签: python arrays anagram

我试图通过一个数组并删除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

4 个答案:

答案 0 :(得分:1)

只需对现有代码进行一些小调整就可以了。

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']

答案 1 :(得分:0)

您的计划中的第一个问题是,您是在for循环之外初始化t0,因此您只需检查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值和字符串匹配的长度,如果它们是anagram。

此方法的示例代码 -

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']

答案 2 :(得分:0)

另一种方法

使用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']
  

这里的关键是使用itertools中的itertools.groupby   模块,它将列表中的项目组合在一起。

     

我们提供给groupby的列表必须先进行排序才能通过   它排序(b,键=排序)。这里的诀窍是排序可以采取   关键功能,将根据此功能的输出进行排序,如此   我们再次传递排序作为关键功能,这将排序   按字母顺序使用字符串的字母。没有必要   定义我们自己的函数或创建一个lambda。

     

groupby采用一个关键函数,用于判断项目是否应该是   组合在一起,我们可以再次传递它内置的排序   功能

来源:Finding and grouping anagrams by Python

答案 3 :(得分:0)

实际上你的解决方案是错误的,使用2 for循环的想法效率不高。你正在迭代你的列表2次,并在你的元素上应用''.join(sorted()) 2次,你也要将每个元素与它自己进行比较!相反,您可以使用字典来获取anagram元素的索引,并迭代列表的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']

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

>>> 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']