![](/img/trans.png)
[英]I am writing a program to find the anagrams from a list of words and output the anagrams in different lists but in an alphabetical order
[英]Create lists of anagrams from a list of words
我想从单词列表中找到创建字谜列表。 我应该在我的代码或递归中使用另一个循环吗?
some_list = ['bad', 'app', 'sad', 'mad', 'dab','pge', 'bda', 'ppa', 'das', 'dba']
new_list = [some_list[0]]
i = 0
while i+1 < len(some_list):
if (''.join(sorted(some_list[0]))) == (''.join(sorted(some_list[i+1]))):
new_list.append(some_list[i+1])
i = i+1
else:
i = i+1
print(new_list)
['bad', 'dab', 'bda', 'dba']
。 但我也想要更多来自some_list
的其他字谜列表。 我希望输出是: - ['app', 'ppa']
- ['bad', 'dab', 'bda', 'dba']
- ['sad', 'das']
我建议您编写 Python,而不是 Java 或您在那里模拟的任何其他语言。 这是您在 Python 中的核心代码,具有正常循环且没有所有不必要的东西:
new_list = [some_list[0]]
for word in some_list[1:]:
if sorted(some_list[0]) == sorted(word):
new_list.append(word)
我没有看到递归的用途,但是,是的,您可以围绕它包裹一个外部循环以找到其他字谜组。
虽然这是我的做法,但使用有用的itertools.groupby :
for _, group in groupby(sorted(some_list, key=sorted), sorted):
group = list(group)
if len(group) > 1:
print(group)
那打印:
['bad', 'dab', 'bda', 'dba']
['sad', 'das']
['app', 'ppa']
通过对组进行排序来解决已更改问题的替代解决方案:
groups = (list(group) for _, group in groupby(sorted(some_list, key=sorted), sorted))
print([group for group in sorted(groups) if len(group) > 1])
输出:
[['app', 'ppa'], ['bad', 'dab', 'bda', 'dba'], ['sad', 'das']]
您的问题是您在列表中循环了一次,因为您需要根据所有单词进行循环。
但我建议此任务的另一种方法,您可以使用itertools.groupby
和使用operator.itemgetter
排序的函数:
some_list = ['bad', 'app', 'sad', 'mad', 'dab','pge', 'bda', 'ppa', 'das', 'dba']
from operator import itemgetter
from itertools import groupby
s=sorted([(i,''.join(sorted(j))) for i,j in enumerate(some_list)],key=itemgetter(1))
inds= [zip(*g)[0] for _,g in groupby(s,itemgetter(1))]
print [itemgetter(*i)(some_list) for i in inds]
结果 :
[('bad', 'dab', 'bda', 'dba'), 'mad', ('sad', 'das'), ('app', 'ppa'), 'pge']
我在这里所做的就是使用sorted
和enumerate
创建一个带有这些索引的排序单词列表:
sorted([(i,''.join(sorted(j))) for i,j in enumerate(some_list)],key=itemgetter(1))
[(0, 'abd'), (4, 'abd'), (6, 'abd'), (9, 'abd'), (3, 'adm'), (2, 'ads'), (8, 'ads'), (1, 'app'), (7, 'app'), (5, 'egp')]
然后我们需要根据第二个元素对这些对进行分组并获取第一个元素(索引),因此我们将拥有以下元组列表:
[(0, 4, 6, 9), (3,), (2, 8), (1, 7), (5,)]
每个元组都包含那些排序表示相同的单词的索引。
最后,您只需要根据前面的索引获取主列表的元素:
[itemgetter(*i)(some_list) for i in inds]
[('bad', 'dab', 'bda', 'dba'), 'mad', ('sad', 'das'), ('app', 'ppa'), 'pge']
1) 创建一个函数anagrams(word)
,它像您的代码一样返回单个单词的 anagrams 列表。
2)将函数map
到您的单词列表上。
这是一个解决方案:
from itertools import groupby
some_list = ['bad', 'app', 'sad', 'mad', 'dab','pge', 'bda', 'ppa', 'das', 'dba']
some_list_ordered = map( lambda x : "".join( sorted( x) ), some_list )
some_lists = sorted(zip( some_list_ordered, some_list ) )
anagrams = filter( lambda x : len( x ) > 1, [ zip(*v)[1] for k,v in groupby( some_lists, lambda x : x[0] ) ] )
for a in anagrams:
print a
#('bad', 'bda', 'dab', 'dba')
#('das', 'sad')
#('app', 'ppa')
如果您负担得起额外字典的内存开销,那么自然的方法似乎是:
words = ['bad', 'app', 'sad', 'mad', 'dab','pge', 'bda', 'ppa', 'das', 'dba']
anagrams = {}
for word in words:
sword = ''.join(sorted(word))
try:
anagrams[sword].append(word)
except KeyError:
anagrams[sword] = [word]
anagrams_list = [v for v in anagrams.values() if len(v) > 1]
print anagrams_list
输出:
[['app', 'ppa'], ['bad', 'dab', 'bda', 'dba'], ['sad', 'das']]
编辑:如以下评论中所述,如果语法不打扰您,您可以使用dict
方法setdefault
替换try...except
块:
words = ['bad', 'app', 'sad', 'mad', 'dab','pge', 'bda', 'ppa', 'das', 'dba']
anagrams = {}
for word in words:
sword = ''.join(sorted(word))
anagrams.setdefault(sword, []).append(word)
anagrams_list = [v for v in anagrams.values() if len(v) > 1]
print anagrams_list
您可以将字典中的单词分组,使用排序后的单词作为关键字,过滤掉值不包含至少两个元素的单词,使用OrderedDict保持顺序:
some_list = ['bad', 'app', 'sad', 'mad', 'dab','pge', 'bda', 'ppa', 'das', 'dba']
from collections import OrderedDict
od = OrderedDict()
for ele in some_list:
srt = "".join(sorted(ele))
od.setdefault(srt,[]).append(ele)
print(filter(lambda x: len(x) > 1, od.values()))
[['bad', 'dab', 'bda', 'dba'], ['app', 'ppa'], ['sad', 'das']]
或者使用循环并附加到列表中,使用临时列表来收集常用词:
new_list = []
from collections import OrderedDict
for ele in OrderedDict.fromkeys("".join(sorted(ele)) for ele in some_list):
temp = []
for s in some_list:
if ele == ''.join(sorted(s)):
temp.append(s)
if len(temp) > 1:
new_list.append(temp)
如果顺序无关紧要,则defaultdict会更有效:
from collections import defaultdict
d = defaultdict(list)
for ele in some_list:
d[''.join(sorted(ele))].append(ele)
print(filter(lambda x: len(x) > 1, d.values()))
[['app', 'ppa'], ['bad', 'dab', 'bda', 'dba'], ['sad', 'das']]
import java.util.*;
public class GroupAnagramsTogether {
public static void main(String[] args)
{
String [] input = new String [] {"bad", "app", "sad", "mad", "dab","pge", "bda", "ppa", "das", "dba"};
System.out.println("Input: " + Arrays.toString(input));
List<List<String>> result = groupAnagram(input);
System.out.println(result);
}
private static List<List<String>> groupAnagram(String[] input)
{
List<List<String>> list = new ArrayList<List<String>>();
HashMap<String, List<String>> mp = new HashMap<String, List<String>>();
for(String s : input)
{
char[] ch = s.toCharArray();
Arrays.sort(ch);
String key = new String(ch);
if(mp.containsKey(key))
{
mp.get(key).add(s);
}
else
{
List<String> strList = new ArrayList<String>();
strList.add(s);
mp.put(key,strList);
}
}
list.addAll(mp.values());
return list;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.