在具有同义词的字典中查找描述的有效方法

时间:2020-06-05 16:10:42

标签: javascript arrays performance optimization reduce

我具有以下结构:

const dictionary = [
  {
    words: ["foo", "bar"],
    desc: "This is a description"
  },
  {
    words: ["some", "word"],
    desc: "This is another description"
  }
]

我想访问给定单词的desc。例如:

getDescription(dictionary, "some") // "This is another description"

我对getDescription的最初实现是这样的:

function getDescription(list, word) {
  return list.find(item => item.words.includes(word)).desc
}

这是一种非常简单的方法,但是我想知道是否可以将list转换为其他内容以使其更有效率(在速度方面),如果说list有5000个项目,其中words的范围是1到5或6。

例如,这种初始转换会有所帮助吗?:

list = list.reduce((acc, item) => ({
    ...acc,
    ...item.words.reduce((acc, word) => ({
      ...acc,
      [word]: item.desc
    }), {})
  }), {}
  )
}

它将重复很多描述,但是访问将是即时的(list["some"] // This is another description)。

这些担心是吗?我会感觉到任何性能的速度差异吗?优化,还是只是浪费时间?

1 个答案:

答案 0 :(得分:0)

dictionary上进行任何预处理都会提高您的性能。将其转换为对象可以将复杂度从O(n)降低到O(1)。就是说,您应该将字典通过单词转换为Map,因为它们是为此类事物创建的。通常,像Elasticsearch这样的inverted index都是这样工作的。

const dictionary = [
  {
    words: ["foo", "bar"],
    desc: "This is a description"
  },
  {
    words: ["some", "word"],
    desc: "This is another description"
  }
]

const { pipe, map, reduce } = rubico

const incrementMap = (m, [word, desc]) => {
  if (m.has(word)) {
    m.get(word).push(desc)
  } else {
    m.set(word, [desc])
  }
  return m
}

const flatten = arr => arr.flat(1)

// dictionary_arr => inverted_index
const createInvertedIndex = pipe([
  map(({ words, desc }) => map(
    word => [word, desc],
  )(words)),
  flatten,
  reduce(incrementMap, new Map()),
])

const maptionary = createInvertedIndex(dictionary)

console.log('maptionary.get(\'some\')', maptionary.get('some'))
<script src="https://unpkg.com/rubico/index.js"></script>

上面的示例使用了我的库rubico。我建议您使用tour更好地了解正在发生的事情。