sorted_set.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*!
  2. * lunr.SortedSet
  3. * Copyright (C) @YEAR Oliver Nightingale
  4. */
  5. /**
  6. * lunr.SortedSets are used to maintain an array of uniq values in a sorted
  7. * order.
  8. *
  9. * @constructor
  10. */
  11. lunr.SortedSet = function () {
  12. this.length = 0
  13. this.elements = []
  14. }
  15. /**
  16. * Loads a previously serialised sorted set.
  17. *
  18. * @param {Array} serialisedData The serialised set to load.
  19. * @returns {lunr.SortedSet}
  20. * @memberOf SortedSet
  21. */
  22. lunr.SortedSet.load = function (serialisedData) {
  23. var set = new this
  24. set.elements = serialisedData
  25. set.length = serialisedData.length
  26. return set
  27. }
  28. /**
  29. * Inserts new items into the set in the correct position to maintain the
  30. * order.
  31. *
  32. * @param {Object} The objects to add to this set.
  33. * @memberOf SortedSet
  34. */
  35. lunr.SortedSet.prototype.add = function () {
  36. var i, element
  37. for (i = 0; i < arguments.length; i++) {
  38. element = arguments[i]
  39. if (~this.indexOf(element)) continue
  40. this.elements.splice(this.locationFor(element), 0, element)
  41. }
  42. this.length = this.elements.length
  43. }
  44. /**
  45. * Converts this sorted set into an array.
  46. *
  47. * @returns {Array}
  48. * @memberOf SortedSet
  49. */
  50. lunr.SortedSet.prototype.toArray = function () {
  51. return this.elements.slice()
  52. }
  53. /**
  54. * Creates a new array with the results of calling a provided function on every
  55. * element in this sorted set.
  56. *
  57. * Delegates to Array.prototype.map and has the same signature.
  58. *
  59. * @param {Function} fn The function that is called on each element of the
  60. * set.
  61. * @param {Object} ctx An optional object that can be used as the context
  62. * for the function fn.
  63. * @returns {Array}
  64. * @memberOf SortedSet
  65. */
  66. lunr.SortedSet.prototype.map = function (fn, ctx) {
  67. return this.elements.map(fn, ctx)
  68. }
  69. /**
  70. * Executes a provided function once per sorted set element.
  71. *
  72. * Delegates to Array.prototype.forEach and has the same signature.
  73. *
  74. * @param {Function} fn The function that is called on each element of the
  75. * set.
  76. * @param {Object} ctx An optional object that can be used as the context
  77. * @memberOf SortedSet
  78. * for the function fn.
  79. */
  80. lunr.SortedSet.prototype.forEach = function (fn, ctx) {
  81. return this.elements.forEach(fn, ctx)
  82. }
  83. /**
  84. * Returns the index at which a given element can be found in the
  85. * sorted set, or -1 if it is not present.
  86. *
  87. * @param {Object} elem The object to locate in the sorted set.
  88. * @returns {Number}
  89. * @memberOf SortedSet
  90. */
  91. lunr.SortedSet.prototype.indexOf = function (elem) {
  92. var start = 0,
  93. end = this.elements.length,
  94. sectionLength = end - start,
  95. pivot = start + Math.floor(sectionLength / 2),
  96. pivotElem = this.elements[pivot]
  97. while (sectionLength > 1) {
  98. if (pivotElem === elem) return pivot
  99. if (pivotElem < elem) start = pivot
  100. if (pivotElem > elem) end = pivot
  101. sectionLength = end - start
  102. pivot = start + Math.floor(sectionLength / 2)
  103. pivotElem = this.elements[pivot]
  104. }
  105. if (pivotElem === elem) return pivot
  106. return -1
  107. }
  108. /**
  109. * Returns the position within the sorted set that an element should be
  110. * inserted at to maintain the current order of the set.
  111. *
  112. * This function assumes that the element to search for does not already exist
  113. * in the sorted set.
  114. *
  115. * @param {Object} elem The elem to find the position for in the set
  116. * @returns {Number}
  117. * @memberOf SortedSet
  118. */
  119. lunr.SortedSet.prototype.locationFor = function (elem) {
  120. var start = 0,
  121. end = this.elements.length,
  122. sectionLength = end - start,
  123. pivot = start + Math.floor(sectionLength / 2),
  124. pivotElem = this.elements[pivot]
  125. while (sectionLength > 1) {
  126. if (pivotElem < elem) start = pivot
  127. if (pivotElem > elem) end = pivot
  128. sectionLength = end - start
  129. pivot = start + Math.floor(sectionLength / 2)
  130. pivotElem = this.elements[pivot]
  131. }
  132. if (pivotElem > elem) return pivot
  133. if (pivotElem < elem) return pivot + 1
  134. }
  135. /**
  136. * Creates a new lunr.SortedSet that contains the elements in the intersection
  137. * of this set and the passed set.
  138. *
  139. * @param {lunr.SortedSet} otherSet The set to intersect with this set.
  140. * @returns {lunr.SortedSet}
  141. * @memberOf SortedSet
  142. */
  143. lunr.SortedSet.prototype.intersect = function (otherSet) {
  144. var intersectSet = new lunr.SortedSet,
  145. i = 0, j = 0,
  146. a_len = this.length, b_len = otherSet.length,
  147. a = this.elements, b = otherSet.elements
  148. while (true) {
  149. if (i > a_len - 1 || j > b_len - 1) break
  150. if (a[i] === b[j]) {
  151. intersectSet.add(a[i])
  152. i++, j++
  153. continue
  154. }
  155. if (a[i] < b[j]) {
  156. i++
  157. continue
  158. }
  159. if (a[i] > b[j]) {
  160. j++
  161. continue
  162. }
  163. };
  164. return intersectSet
  165. }
  166. /**
  167. * Makes a copy of this set
  168. *
  169. * @returns {lunr.SortedSet}
  170. * @memberOf SortedSet
  171. */
  172. lunr.SortedSet.prototype.clone = function () {
  173. var clone = new lunr.SortedSet
  174. clone.elements = this.toArray()
  175. clone.length = clone.elements.length
  176. return clone
  177. }
  178. /**
  179. * Creates a new lunr.SortedSet that contains the elements in the union
  180. * of this set and the passed set.
  181. *
  182. * @param {lunr.SortedSet} otherSet The set to union with this set.
  183. * @returns {lunr.SortedSet}
  184. * @memberOf SortedSet
  185. */
  186. lunr.SortedSet.prototype.union = function (otherSet) {
  187. var longSet, shortSet, unionSet
  188. if (this.length >= otherSet.length) {
  189. longSet = this, shortSet = otherSet
  190. } else {
  191. longSet = otherSet, shortSet = this
  192. }
  193. unionSet = longSet.clone()
  194. for(var i = 0, shortSetElements = shortSet.toArray(); i < shortSetElements.length; i++){
  195. unionSet.add(shortSetElements[i])
  196. }
  197. return unionSet
  198. }
  199. /**
  200. * Returns a representation of the sorted set ready for serialisation.
  201. *
  202. * @returns {Array}
  203. * @memberOf SortedSet
  204. */
  205. lunr.SortedSet.prototype.toJSON = function () {
  206. return this.toArray()
  207. }