【发布时间】: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…inenumerations on arrays - 在字符串上甚至更少! -
您应该为每个单词缓存
tmpArray,以便您可以直接比较它们。然后,不要在嵌套循环中比较它们,而是尝试构建一个嵌套决策树,按计数作为键,按字母嵌套(按字母顺序排列深度)。这样您就可以快速查找可能的候选人。
标签: javascript arrays fs