orderby.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. package help
  2. import "sort"
  3. type order struct {
  4. selector func(interface{}) interface{}
  5. compare comparer
  6. desc bool
  7. }
  8. // OrderedQuery is the type returned from OrderBy, OrderByDescending ThenBy and
  9. // ThenByDescending functions.
  10. type OrderedQuery struct {
  11. Query
  12. original Query
  13. orders []order
  14. }
  15. // OrderBy sorts the elements of a collection in ascending order. Elements are
  16. // sorted according to a key.
  17. func (q Query) OrderBy(selector func(interface{}) interface{}) OrderedQuery {
  18. return OrderedQuery{
  19. orders: []order{{selector: selector}},
  20. original: q,
  21. Query: Query{
  22. Iterate: func() Iterator {
  23. items := q.sort([]order{{selector: selector}})
  24. len := len(items)
  25. index := 0
  26. return func() (item interface{}, ok bool) {
  27. ok = index < len
  28. if ok {
  29. item = items[index]
  30. index++
  31. }
  32. return
  33. }
  34. },
  35. },
  36. }
  37. }
  38. // OrderByT is the typed version of OrderBy.
  39. //
  40. // - selectorFn is of type "func(TSource) TKey"
  41. //
  42. // NOTE: OrderBy has better performance than OrderByT.
  43. func (q Query) OrderByT(selectorFn interface{}) OrderedQuery {
  44. selectorGenericFunc, err := newGenericFunc(
  45. "OrderByT", "selectorFn", selectorFn,
  46. simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(genericType))),
  47. )
  48. if err != nil {
  49. panic(err)
  50. }
  51. selectorFunc := func(item interface{}) interface{} {
  52. return selectorGenericFunc.Call(item)
  53. }
  54. return q.OrderBy(selectorFunc)
  55. }
  56. // OrderByDescending sorts the elements of a collection in descending order.
  57. // Elements are sorted according to a key.
  58. func (q Query) OrderByDescending(selector func(interface{}) interface{}) OrderedQuery {
  59. return OrderedQuery{
  60. orders: []order{{selector: selector, desc: true}},
  61. original: q,
  62. Query: Query{
  63. Iterate: func() Iterator {
  64. items := q.sort([]order{{selector: selector, desc: true}})
  65. len := len(items)
  66. index := 0
  67. return func() (item interface{}, ok bool) {
  68. ok = index < len
  69. if ok {
  70. item = items[index]
  71. index++
  72. }
  73. return
  74. }
  75. },
  76. },
  77. }
  78. }
  79. // OrderByDescendingT is the typed version of OrderByDescending.
  80. // - selectorFn is of type "func(TSource) TKey"
  81. // NOTE: OrderByDescending has better performance than OrderByDescendingT.
  82. func (q Query) OrderByDescendingT(selectorFn interface{}) OrderedQuery {
  83. selectorGenericFunc, err := newGenericFunc(
  84. "OrderByDescendingT", "selectorFn", selectorFn,
  85. simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(genericType))),
  86. )
  87. if err != nil {
  88. panic(err)
  89. }
  90. selectorFunc := func(item interface{}) interface{} {
  91. return selectorGenericFunc.Call(item)
  92. }
  93. return q.OrderByDescending(selectorFunc)
  94. }
  95. // ThenBy performs a subsequent ordering of the elements in a collection in
  96. // ascending order. This method enables you to specify multiple sort criteria by
  97. // applying any number of ThenBy or ThenByDescending methods.
  98. func (oq OrderedQuery) ThenBy(
  99. selector func(interface{}) interface{}) OrderedQuery {
  100. return OrderedQuery{
  101. orders: append(oq.orders, order{selector: selector}),
  102. original: oq.original,
  103. Query: Query{
  104. Iterate: func() Iterator {
  105. items := oq.original.sort(append(oq.orders, order{selector: selector}))
  106. len := len(items)
  107. index := 0
  108. return func() (item interface{}, ok bool) {
  109. ok = index < len
  110. if ok {
  111. item = items[index]
  112. index++
  113. }
  114. return
  115. }
  116. },
  117. },
  118. }
  119. }
  120. // ThenByT is the typed version of ThenBy.
  121. // - selectorFn is of type "func(TSource) TKey"
  122. // NOTE: ThenBy has better performance than ThenByT.
  123. func (oq OrderedQuery) ThenByT(selectorFn interface{}) OrderedQuery {
  124. selectorGenericFunc, err := newGenericFunc(
  125. "ThenByT", "selectorFn", selectorFn,
  126. simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(genericType))),
  127. )
  128. if err != nil {
  129. panic(err)
  130. }
  131. selectorFunc := func(item interface{}) interface{} {
  132. return selectorGenericFunc.Call(item)
  133. }
  134. return oq.ThenBy(selectorFunc)
  135. }
  136. // ThenByDescending performs a subsequent ordering of the elements in a
  137. // collection in descending order. This method enables you to specify multiple
  138. // sort criteria by applying any number of ThenBy or ThenByDescending methods.
  139. func (oq OrderedQuery) ThenByDescending(selector func(interface{}) interface{}) OrderedQuery {
  140. return OrderedQuery{
  141. orders: append(oq.orders, order{selector: selector, desc: true}),
  142. original: oq.original,
  143. Query: Query{
  144. Iterate: func() Iterator {
  145. items := oq.original.sort(append(oq.orders, order{selector: selector, desc: true}))
  146. len := len(items)
  147. index := 0
  148. return func() (item interface{}, ok bool) {
  149. ok = index < len
  150. if ok {
  151. item = items[index]
  152. index++
  153. }
  154. return
  155. }
  156. },
  157. },
  158. }
  159. }
  160. // ThenByDescendingT is the typed version of ThenByDescending.
  161. // - selectorFn is of type "func(TSource) TKey"
  162. // NOTE: ThenByDescending has better performance than ThenByDescendingT.
  163. func (oq OrderedQuery) ThenByDescendingT(selectorFn interface{}) OrderedQuery {
  164. selectorFunc, ok := selectorFn.(func(interface{}) interface{})
  165. if !ok {
  166. selectorGenericFunc, err := newGenericFunc(
  167. "ThenByDescending", "selectorFn", selectorFn,
  168. simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(genericType))),
  169. )
  170. if err != nil {
  171. panic(err)
  172. }
  173. selectorFunc = func(item interface{}) interface{} {
  174. return selectorGenericFunc.Call(item)
  175. }
  176. }
  177. return oq.ThenByDescending(selectorFunc)
  178. }
  179. // Sort returns a new query by sorting elements with provided less function in
  180. // ascending order. The comparer function should return true if the parameter i
  181. // is less than j. While this method is uglier than chaining OrderBy,
  182. // OrderByDescending, ThenBy and ThenByDescending methods, it's performance is
  183. // much better.
  184. func (q Query) Sort(less func(i, j interface{}) bool) Query {
  185. return Query{
  186. Iterate: func() Iterator {
  187. items := q.lessSort(less)
  188. len := len(items)
  189. index := 0
  190. return func() (item interface{}, ok bool) {
  191. ok = index < len
  192. if ok {
  193. item = items[index]
  194. index++
  195. }
  196. return
  197. }
  198. },
  199. }
  200. }
  201. // SortT is the typed version of Sort.
  202. // - lessFn is of type "func(TSource,TSource) bool"
  203. // NOTE: Sort has better performance than SortT.
  204. func (q Query) SortT(lessFn interface{}) Query {
  205. lessGenericFunc, err := newGenericFunc(
  206. "SortT", "lessFn", lessFn,
  207. simpleParamValidator(newElemTypeSlice(new(genericType), new(genericType)), newElemTypeSlice(new(bool))),
  208. )
  209. if err != nil {
  210. panic(err)
  211. }
  212. lessFunc := func(i, j interface{}) bool {
  213. return lessGenericFunc.Call(i, j).(bool)
  214. }
  215. return q.Sort(lessFunc)
  216. }
  217. type sorter struct {
  218. items []interface{}
  219. less func(i, j interface{}) bool
  220. }
  221. func (s sorter) Len() int {
  222. return len(s.items)
  223. }
  224. func (s sorter) Swap(i, j int) {
  225. s.items[i], s.items[j] = s.items[j], s.items[i]
  226. }
  227. func (s sorter) Less(i, j int) bool {
  228. return s.less(s.items[i], s.items[j])
  229. }
  230. func (q Query) sort(orders []order) (r []interface{}) {
  231. next := q.Iterate()
  232. for item, ok := next(); ok; item, ok = next() {
  233. r = append(r, item)
  234. }
  235. if len(r) == 0 {
  236. return
  237. }
  238. for i, j := range orders {
  239. orders[i].compare = getComparer(j.selector(r[0]))
  240. }
  241. s := sorter{
  242. items: r,
  243. less: func(i, j interface{}) bool {
  244. for _, order := range orders {
  245. x, y := order.selector(i), order.selector(j)
  246. switch order.compare(x, y) {
  247. case 0:
  248. continue
  249. case -1:
  250. return !order.desc
  251. default:
  252. return order.desc
  253. }
  254. }
  255. return false
  256. }}
  257. sort.Sort(s)
  258. return
  259. }
  260. func (q Query) lessSort(less func(i, j interface{}) bool) (r []interface{}) {
  261. next := q.Iterate()
  262. for item, ok := next(); ok; item, ok = next() {
  263. r = append(r, item)
  264. }
  265. s := sorter{items: r, less: less}
  266. sort.Sort(s)
  267. return
  268. }