23

提供された一連の単語内のすべてのアナグラムを見つけるために、JavaScript でプログラムを作成することになっています。例えば:

monk, konm, nkom, bbc, cbb, dell, ledl, llde

出力は次の行に分類する必要があります。

1. monk konm, nkom;
2. bbc cbb;
3. dell ledl, llde;

私はすでにそれらをアルファベット順にソートし、配列に入れました。すなわち:

kmno kmno bbc bbc dell dell

ただし、配列内で一致するアナグラムを比較して見つけることに固執しています。

どんな助けでも大歓迎です。

4

33 に答える 33

20

これが私の見解です:

var input = "monk, konm, bbc, cbb, dell, ledl";
var words = input.split(", ");

for (var i = 0; i < words.length; i++) {

  var word = words[i];
  var alphabetical = word.split("").sort().join("");

  for (var j = 0; j < words.length; j++) {

    if (i === j) {
      continue;
    }

    var other = words[j];
    if (alphabetical === other.split("").sort().join("")) {
      console.log(word + " - " + other + " (" + i + ", " + j + ")");
    }
  }
}

ここで、出力は次のようになります(単語、一致、および両方のインデックス):

monk - konm (0, 1)
konm - monk (1, 0)
bbc - cbb (2, 3)
cbb - bbc (3, 2)
dell - ledl (4, 5)
ledl - dell (5, 4)

文字をアルファベット順に取得するために、split( "")を使用してsort()と呼ばれる配列を取得し、join( "")を使用して配列から文字列を取得しました。

于 2009-05-26T08:20:12.227 に答える
19

Javascriptオブジェクトは、本質的にキー/値ストアであるため、この目的に最適です。

// Words to match
var words = ["dell", "ledl", "abc", "cba"];

// The output object
var anagrams = {};

for (var i in words) {
    var word = words[i];

    // sort the word like you've already described
    var sorted = sortWord(word);

    // If the key already exists, we just push
    // the new word on the the array
    if (anagrams[sorted] != null) {
        anagrams[sorted].push(word);
    } 
    // Otherwise we create an array with the word
    // and insert it into the object
    else {
        anagrams[sorted] = [ word ];
    }
}

// Output result
for (var sorted in anagrams) {
    var words = anagrams[sorted];
    var sep = ",";
    var out = "";
    for (var n in words) {
        out += sep + words[n];
        sep = "";
    }
    document.writeln(sorted + ": " + out + "<br />");
}
于 2009-05-26T08:06:34.157 に答える
4

インタビューでこんな質問がありました。単語の配列 ['cat', 'dog', 'tac', 'god', 'act'] を指定すると、すべてのアナグラムがグループ化された配列が返されます。アナグラムが一意であることを確認します。

var arr = ['cat', 'dog', 'tac', 'god', 'act'];

var allAnagrams = function(arr) {
    var anagrams = {};
    arr.forEach(function(str) {
        var recurse = function(ana, str) {
            if (str === '') 
                anagrams[ana] = 1;
            for (var i = 0; i < str.length; i++)
                recurse(ana + str[i], str.slice(0, i) + str.slice(i + 1));
        };
        recurse('', str);
    });
    return Object.keys(anagrams);
}

console.log(allAnagrams(arr));
//["cat", "cta", "act", "atc", "tca", "tac", "dog", "dgo", "odg", "ogd", "gdo", "god"]
于 2015-02-10T20:57:01.837 に答える
3

I know this is an ancient post...but I just recently got nailed during an interview on this one. So, here is my 'new & improved' answer:

var AnagramStringMiningExample = function () {

/* Author: Dennis Baughn
*  This has also been posted at: 
*  http://stackoverflow.com/questions/909449/anagrams-finder-in-javascript/5642437#5642437

*  Free, private members of the closure and anonymous, innner function
*  We will be building a hashtable for anagrams found, with the key 
*  being the alphabetical char sort (see sortCharArray()) 
*  that the anagrams all have in common. 
*/
    var dHash = {};

    var sortCharArray = function(word) {
        return word.split("").sort().join("");
    };

/* End free, private members for the closure and anonymous, innner function */

/* This goes through the dictionary entries. 
 *  finds the anagrams (if any) for each word,
 *  and then populates them in the hashtable. 
 *  Everything strictly local gets de-allocated 
 *  so as not to pollute the closure with 'junk DNA'.
*/
    (function() {
       /* 'dictionary' referring to English dictionary entries. For a real 
        *  English language dictionary, we could be looking at 20,000+ words, so 
        *  an array instead of a string would be needed.
        */
       var dictionaryEntries = "buddy,pan,nap,toot,toto,anestri,asterin,eranist,nastier,ratines,resiant,restain,retains,retinas,retsina,sainter,stainer,starnie,stearin";
       /* This could probably be refactored better.  
        * It creates the actual hashtable entries. */
       var populateDictionaryHash = function(keyword, newWord) {
          var anagrams = dHash[keyword];
          if (anagrams && anagrams.indexOf(newWord) < 0) 
            dHash[keyword] = (anagrams+','+newWord);
          else dHash[keyword] = newWord;
       };

       var words = dictionaryEntries.split(",");

       /* Old School answer, brute force
       for (var i = words.length - 1; i >= 0; i--) {
        var firstWord = words[i];
        var sortedFirst = sortCharArray(firstWord);
        for (var k = words.length - 1; k >= 0; k--) {
               var secondWord = words[k];
           if (i === k) continue;
            var sortedSecond = sortCharArray(secondWord);
            if (sortedFirst === sortedSecond)   
                       populateDictionaryHash(sortedFirst, secondWord);
        }
       }/*

        /*Better Method for JS, using JS Array.reduce(callback) with scope binding on callback function */
        words.reduce(function (prev, cur, index, array) { 
            var sortedFirst = this.sortCharArray(prev);
            var sortedSecond = this.sortCharArray(cur); 
            if (sortedFirst === sortedSecond) {
                var anagrams = this.dHash[sortedFirst];
                if (anagrams && anagrams.indexOf(cur) < 0) 
                   this.dHash[sortedFirst] = (anagrams + ',' + cur);
                else 
                   this.dHash[sortedFirst] = prev + ','+ cur;                    
            }
            return cur;
        }.bind(this));
    }());

    /* return in a nice, tightly-scoped closure the actual function 
     *  to search for any anagrams for searchword provided in args and render results. 
    */
    return function(searchWord) {
       var keyToSearch = sortCharArray(searchWord);
       document.writeln('<p>');
       if (dHash.hasOwnProperty(keyToSearch)) {
        var anagrams = dHash[keyToSearch];
        document.writeln(searchWord + ' is part of a collection of '+anagrams.split(',').length+' anagrams: ' + anagrams+'.');
       } else document.writeln(searchWord + ' does not have anagrams.');
       document.writeln('<\/p>');
    };
};

Here is how it executes:

var checkForAnagrams = new AnagramStringMiningExample();
checkForAnagrams('toot');
checkForAnagrams('pan');
checkForAnagrams('retinas');
checkForAnagrams('buddy');

Here is the output of the above:

toot is part of a collection of 2 anagrams: toto,toot.

pan is part of a collection of 2 anagrams: nap,pan.

retinas is part of a collection of 14 anagrams: stearin,anestri,asterin,eranist,nastier,ratines,resiant,restain,retains,retinas,retsina,sainter,stainer,starnie.

buddy does not have anagrams.

于 2011-04-12T22:36:50.120 に答える
2

この古い投稿に対する私の解決策:

// Words to match
var words = ["dell", "ledl", "abc", "cba"],
    map = {};

//Normalize all the words 
var normalizedWords = words.map( function( word ){
  return word.split('').sort().join('');
});

//Create a map: normalizedWord -> real word(s)
normalizedWords.forEach( function ( normalizedWord, index){
  map[normalizedWord] = map[normalizedWord] || [];
  map[normalizedWord].push( words[index] );
});

//All entries in the map with an array with size > 1 are anagrams
Object.keys( map ).forEach( function( normalizedWord , index  ){
  var combinations = map[normalizedWord];
  if( combinations.length > 1 ){
    console.log( index + ". " + combinations.join(' ') );
  }
});

基本的に、文字を並べ替えてすべての単語を正規化し、stackoverflowacefkloorstvwになるようにし、正規化された単語と元の単語の間のマップを作成し、正規化された単語に複数の単語が接続されているかを判断します -> それはアナグラムです。

于 2014-07-16T13:43:09.170 に答える
1

簡単な例があります

function isAnagram(strFirst, strSecond) {

 if(strFirst.length != strSecond.length)
       return false;

 var tempString1 = strFirst.toLowerCase();
 var tempString2 = strSecond.toLowerCase();

 var matched = true ;
 var cnt = 0;
 while(tempString1.length){
    if(tempString2.length < 1)
        break;
    if(tempString2.indexOf(tempString1[cnt]) > -1 )
        tempString2 = tempString2.replace(tempString1[cnt],'');
    else
        return false;

    cnt++;
 }

 return matched ;

 }

関数の呼び出しは、isAnagram("Army",Mary); 関数が返すtrueか、またはfalse

于 2016-12-08T11:52:52.077 に答える
1

もしかしてこれ?

function anagram (array) {
    var organized = {};
    for (var i = 0; i < array.length; i++) {
        var word = array[i].split('').sort().join('');
        if (!organized.hasOwnProperty(word)) {
            organized[word] = [];
        }
        organized[word].push(array[i]);
    }    
    return organized;
}


anagram(['kmno', 'okmn', 'omkn', 'dell', 'ledl', 'ok', 'ko']) // Example

次のようなものが返されます

{
    dell: ['dell', 'ledl'],
    kmno: ['kmno', okmn', 'omkn'],
    ko: ['ok', ko']
}

これはあなたが望んでいたものの単純なバージョンであり、たとえば重複を避けることで改善される可能性があります.

于 2016-12-28T18:30:58.113 に答える
0

私のソリューションにはより多くのコードがありますが、.sort() の使用を回避しているため、このソリューションの方が時間の複雑さが少ないと思います。代わりに、すべての単語からハッシュを作成し、ハッシュを比較します。

const wordToHash = word => {
  const hash = {};
  // Make all lower case and remove spaces
  [...word.toLowerCase().replace(/ /g, '')].forEach(letter => hash[letter] ? hash[letter] += 1 : hash[letter] = 1);
  return hash;
}
const hashesEqual = (obj1, obj2) => {
  const keys1 = Object.keys(obj1), keys2 = Object.keys(obj2);
  let match = true;
  if(keys1.length !== keys2.length) return false;
  for(const key in keys1) { if(obj1[key] !== obj2[key]) match = false; break; }
  return match;
}
const checkAnagrams = (word1, word2) => {
  const hash1 = wordToHash(word1), hash2 = wordToHash(word2);
  return hashesEqual(hash1, hash2);
}
console.log( checkAnagrams("Dormitory", "Dirty room") );
于 2020-05-01T03:45:04.400 に答える
0
const getAnagrams = (...args) => {
    const anagrams = {};

    args.forEach((arg) => {        
        const letters = arg.split("").sort().join("");

        if (anagrams[letters]) {
            anagrams[letters].push(arg);
        } else {
            anagrams[letters] = [arg];
        }
    });
    
    return Object.values(anagrams);
}
于 2021-02-21T17:16:56.603 に答える