【问题标题】:Speeding the process of gathering subwords that you can spell with the characters of other words加快收集可以与其他单词字符拼写的子单词的过程
【发布时间】:2020-01-28 05:48:40
【问题描述】:

此代码的目标是列出一个数组数组,其中包含其索引长度的对象词,其中还包含一个子词数组,其中也包含其索引长度的子词。这些子词是您可以用词本身的字符拼写的词。我正在尝试优化我的代码,以便它能够以更快的速度处理大约 81,000 个单词。当前程序运行并将完成该过程,但需要几个小时才能完成。我正在努力寻找可以在我的代码中最好的地方进行更改以减少运行所需的时间。

这是一个示例 words.txt 文件。

do
dog
eat
go
god
goo
good
tea

下面是上面 txt 文件的预期 subwords.json 输出。

[
    [],
    [],
    [
        {
            "word": "do",
            "subwords": [
                [],
                [],
                []
            ]
        },
        {
            "word": "go",
            "subwords": [
                [],
                [],
                []
            ]
        }
    ],
    [
        {
            "word": "dog",
            "subwords": [
                [],
                [],
                [
                    "do",
                    "go"
                ],
                [
                    "god"
                ]
            ]
        },
        {
            "word": "eat",
            "subwords": [
                [],
                [],
                [],
                [
                    "tea"
                ]
            ]
        },
        {
            "word": "god",
            "subwords": [
                [],
                [],
                [
                    "do",
                    "go"
                ],
                [
                    "dog"
                ]
            ]
        },
        {
            "word": "goo",
            "subwords": [
                [],
                [],
                [
                    "go"
                ],
                []
            ]
        },
        {
            "word": "tea",
            "subwords": [
                [],
                [],
                [],
                [
                    "eat"
                ]
            ]
        }
    ]
]

下面是正在运行的代码,调用 words.txt 并输出 subwords.json

const fs = require('fs')

const totalTalkText = fs.readFileSync('words.txt').toString()

const sortedWords = totalTalkText
  .toLowerCase()
  .split(/[^a-zA-Z]+/g)
  .sort()
  .sort((a, b) => {
    return a.length - b.length
  })

const finalData = new Array()

for (i = 0; i < sortedWords[0].length; i++) {
  finalData[i] = []
}

sortedWords.forEach((word, index) => {
  const subwordsArray = new Array()
  let wordObject = {
    word: word
  }

  if (finalData.indexOf(word.length) === -1) {
    finalData[word.length] = new Array()
  }

  sortedWords.some(subword => {
    if (subword.length > word.length) return

    if (subwordsArray.indexOf(subword.length) === -1) {
      subwordsArray[subword.length] = new Array()

      for (i = 0; i < sortedWords[0].length; i++) {
        subwordsArray[i] = []
      }
    }

    if (subword !== '' && word !== subword && isSubword(word, subword)) {
      subwordsArray[subword.length].push(subword)
    }
  })

  wordObject.subwords = subwordsArray

  finalData[word.length].push(wordObject)
  //console.log(`${word}: ${index / 814.88}%`) //This is mostly to help me gauge how long the program would take
})

fs.writeFileSync('subwords.json', JSON.stringify([...finalData]))

function isSubword(word, subword) {
  let tmpArray = new Array(256)

  for (let i = 0; i < 256; i++) tmpArray[i] = 0

  for (let i in word) tmpArray[word.charCodeAt(i)] += 1

  for (let i in subword) {
    tmpArray[subword.charCodeAt(i)] -= 1
    if (tmpArray[subword.charCodeAt(i)] < 0) return false
  }
  return true
}

我一直在尝试找到一种更好的方法来检查一个单词是否是 isSubword 函数中的子词,但没有成功。同样,代码应该在很长一段时间内运行,我只是想让它运行得更快。任何帮助将不胜感激!

【问题讨论】:

  • Don't use for…in enumerations on arrays - 在字符串上甚至更少!
  • 您应该为每个单词缓存tmpArray,以便您可以直接比较它们。然后,不要在嵌套循环中比较它们,而是尝试构建一个嵌套决策树,按计数作为键,按字母嵌套(按字母顺序排列深度)。这样您就可以快速查找可能的候选人。

标签: javascript arrays fs


【解决方案1】:

对于 isSubword 函数,我认为您可以通过使用 while 循环(可中断)而不是 for 循环(始终运行预定次数)来加快速度。这是一个示例,我们将单词和子单词分解为一个字符数组,然后在 while 循环中检查子单词的每个字符是否在单词中,如果是,则将其从单词数组中删除。正如您在控制台日志中看到的那样,如果 while 循环发现单词中不包含的字符,它将停止迭代。

function isSubword(word, subword) {
  const wordArray = word.split("");
  const subwordArray = subword.split("");
  let isSubword = true;
  let i = 0;
  while(i < subwordArray.length && isSubword){
    const matchIndex = wordArray.findIndex(l => l === subwordArray[i] );
    console.log(subwordArray[i]);
    if(matchIndex < 0){
      isSubword = false;
    } else {
      wordArray.splice(matchIndex, 1);
      i += 1;
    }
  }
  return isSubword;
}

console.log(isSubword('test', 'set'));
console.log(isSubword('test', 'if'));
console.log(isSubword('test', 'tt'));
console.log(isSubword('test', 'ttt'));

【讨论】:

    猜你喜欢
    • 2011-07-16
    • 2014-04-29
    • 1970-01-01
    • 2016-11-24
    • 1970-01-01
    • 2015-09-05
    • 1970-01-01
    • 2011-10-02
    • 2018-10-24
    相关资源
    最近更新 更多