たとえば、文字列のリストがある場合:
["car", "tree", "boy", "girl", "arc"...]
そのリストでアナグラムを見つけるにはどうすればよいですか?例えば (car, arc)
。各文字列にforループを使用してみました。異なる長さの文字列を無視するためにif
を使用しましたが、正しい結果を得ることができませんでした。
文字列内の各文字を調べて、リスト内の他の文字と異なる順序で比較するにはどうすればよいですか?
私はいくつかの同様の質問を読みましたが、答えはあまりにも高度でした。何もインポートできず、基本的な機能しか使用できません。
2つの文字列に対してこれを行うには、次のようにします。
def isAnagram(str1, str2):
str1_list = list(str1)
str1_list.sort()
str2_list = list(str2)
str2_list.sort()
return (str1_list == str2_list)
リストの繰り返しに関しては、かなり簡単です
(ソートされたWord、Wordのリスト)の辞書を作成します。同じリストにあるすべての単語は、相互のアナグラムです。
from collections import defaultdict
def load_words(filename='/usr/share/dict/american-english'):
with open(filename) as f:
for Word in f:
yield Word.rstrip()
def get_anagrams(source):
d = defaultdict(list)
for Word in source:
key = "".join(sorted(Word))
d[key].append(Word)
return d
def print_anagrams(Word_source):
d = get_anagrams(Word_source)
for key, anagrams in d.iteritems():
if len(anagrams) > 1:
print(key, anagrams)
Word_source = load_words()
print_anagrams(Word_source)
または:
Word_source = ["car", "tree", "boy", "girl", "arc"]
print_anagrams(Word_source)
解決策の1つは、アナグラムを検索しているWordを並べ替えて(たとえばsorted
を使用して)、代替を並べ替えて比較します。
したがって、リストで「rac」のアナグラムを検索する場合は、['car', 'girl', 'tofu', 'rca']
、コードは次のようになります。
Word = sorted('rac')
alternatives = ['car', 'girl', 'tofu', 'rca']
for alt in alternatives:
if Word == sorted(alt):
print alt
各要素を並べ替えてから、重複を探します。ソート用の組み込み関数があるので、何もインポートする必要はありません
この問題には複数の解決策があります。
古典的なアプローチ
最初に、アナグラムを定義するものを考えてみましょう:2つの単語が同じ文字のセットで構成され、各文字がまったく同じ数である場合、互いにアナグラムです両方の単語の時間。これは基本的に、各単語の文字数のヒストグラムです。これは_collections.Counter
_データ構造の完璧な使用例です( docsを参照 )。アルゴリズムは次のとおりです。
コードは次のとおりです。
_from collections import Counter, defaultdict
def anagram(words):
anagrams = defaultdict(list)
for Word in words:
histogram = Tuple(Counter(Word).items()) # build a hashable histogram
anagrams[histogram].append(Word)
return list(anagrams.values())
keywords = ("hi", "hello", "bye", "helol", "abc", "cab",
"bac", "silenced", "licensed", "declines")
print(anagram(keywords))
_
Counter
の構築はO(l)
であり、各WordのソートはO(n*log(l))
であることに注意してください(lはWordの長さです)。
素数を使用してアナグラムを解く
これは、より高度なソリューションであり、素数の「乗算的一意性」に依存しています。これを参照することができますSO post: 素数を使用したアナグラムの比較 、および サンプルpython実装です 。
何もインポートできないため、要求したforループを含む2つの異なるアプローチがあります。
アプローチ1:Forループと組み込みソート関数
Word_list = ["percussion", "supersonic", "car", "tree", "boy", "girl", "arc"]
# initialize a list
anagram_list = []
for Word_1 in Word_list:
for Word_2 in Word_list:
if Word_1 != Word_2 and (sorted(Word_1)==sorted(Word_2)):
anagram_list.append(Word_1)
print(anagram_list)
アプローチ2:辞書
def freq(Word):
freq_dict = {}
for char in Word:
freq_dict[char] = freq_dict.get(char, 0) + 1
return freq_dict
# initialize a list
anagram_list = []
for Word_1 in Word_list:
for Word_2 in Word_list:
if Word_1 != Word_2 and (freq(Word_1) == freq(Word_2)):
anagram_list.append(Word_1)
print(anagram_list)
これらのアプローチをより詳細に説明したい場合は、 記事 をご覧ください。
以前の回答のほとんどは正しいです。2つの文字列を比較する別の方法があります。この戦略をソートと比較して使用する主な利点は、空間/時間の複雑さであり、これは n log of n です。
1.文字列の長さを確認する
2.頻度辞書を作成し、両者が一致するかどうかを比較して、アナグラムの単語を特定しました
def char_frequency(Word):
frequency = {}
for char in Word:
#if character is in frequency then increment the value
if char in frequency:
frequency[char] += 1
#else add character and set it to 1
else:
frequency[char] = 1
return frequency
a_Word ='google'
b_Word ='ooggle'
#check length of the words
if (len(a_Word) != len(b_Word)):
print ("not anagram")
else:
#here we check the frequecy to see if we get the same
if ( char_frequency(a_Word) == char_frequency(b_Word)):
print("found anagram")
else:
print("no anagram")
def findanagranfromlistofwords(li):
dict = {}
index=0
for i in range(0,len(li)):
originalfirst = li[index]
sortedfirst = ''.join(sorted(str(li[index])))
for j in range(index+1,len(li)):
next = ''.join(sorted(str(li[j])))
print next
if sortedfirst == next:
dict.update({originalfirst:li[j]})
print "dict = ",dict
index+=1
print dict
findanagranfromlistofwords(["car", "tree", "boy", "girl", "arc"])
Pythonのシンプルなソリューション:
def anagram(s1,s2):
# Remove spaces and lowercase letters
s1 = s1.replace(' ','').lower()
s2 = s2.replace(' ','').lower()
# Return sorted match.
return sorted(s1) == sorted(s2)
辞書を使用して、文字列の各文字を1つずつ保存しています。次に、2番目の文字列を反復処理し、辞書内の文字を見つけます。文字が存在する場合は、辞書の対応するキーの数を減らします。
class Anagram:
dict = {}
def __init__(self):
Anagram.dict = {}
def is_anagram(self,s1, s2):
print '***** starting *****'
print '***** convert input strings to lowercase'
s1 = s1.lower()
s2 = s2.lower()
for i in s1:
if i not in Anagram.dict:
Anagram.dict[i] = 1
else:
Anagram.dict[i] += 1
print Anagram.dict
for i in s2:
if i not in Anagram.dict:
return false
else:
Anagram.dict[i] -= 1
print Anagram.dict
for i in Anagram.dict.keys():
if Anagram.dict.get(i) == 0:
del Anagram.dict[i]
if len(Anagram.dict) == 0:
print Anagram.dict
return True
else:
return False
import collections
def find_anagrams(x):
anagrams = [''.join(sorted(list(i))) for i in x]
anagrams_counts = [item for item, count in collections.Counter(anagrams).items() if count > 1]
return [i for i in x if ''.join(sorted(list(i))) in anagrams_counts]
これはうまくいきます:
def find_ana(l):
a=[]
for i in range(len(l)):
for j in range(len(l)):
if (l[i]!=l[j]) and (sorted(l[i])==sorted(l[j])):
a.append(l[i])
a.append(l[j])
return list(set(a))
これはあなたを助けるつもりです:
入力がコンマ区切りの文字列として与えられていると仮定
コンソール入力:abc、bac、car、rac、pqr、acb、acr、abc
in_list = list()
in_list = map(str, raw_input("Enter strings seperated by comma").split(','))
list_anagram = list()
for i in range(0, len(in_list) - 1):
if sorted(in_list[i]) not in list_anagram:
for j in range(i + 1, len(in_list)):
isanagram = (sorted(in_list[i]) == sorted(in_list[j]))
if isanagram:
list_anagram.append(sorted(in_list[i]))
print in_list[i], 'isanagram'
break
pythonのソリューションは以下のようになります:
class Word:
def __init__(self, data, index):
self.data = data
self.index = index
def printAnagrams(arr):
dupArray = []
size = len(arr)
for i in range(size):
dupArray.append(Word(arr[i], i))
for i in range(size):
dupArray[i].data = ''.join(sorted(dupArray[i].data))
dupArray = sorted(dupArray, key=lambda x: x.data)
for i in range(size):
print arr[dupArray[i].index]
def main():
arr = ["dog", "act", "cat", "god", "tac"]
printAnagrams(arr)
if __name__== '__main__':
main()
上記の時間の複雑さは、O(NMLogN + NMLogM)= O(NMlogN)です。