PageRenderTime 24ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/_octopress/source/functions/array_multisort/index.markdown

https://gitlab.com/orvi2014/phpjs
Markdown | 317 lines | 286 code | 31 blank | 0 comment | 0 complexity | bdb1c350f885bea882e9b3e8053ecb4b MD5 | raw file
  1. ---
  2. layout: page
  3. title: "JavaScript array_multisort function"
  4. comments: true
  5. sharing: true
  6. footer: true
  7. alias:
  8. - /functions/view/array_multisort:830
  9. - /functions/view/array_multisort
  10. - /functions/view/830
  11. - /functions/array_multisort:830
  12. - /functions/830
  13. ---
  14. <!-- Generated by Rakefile:build -->
  15. A JavaScript equivalent of PHP's array_multisort
  16. {% codeblock array/array_multisort.js lang:js https://raw.github.com/kvz/phpjs/master/functions/array/array_multisort.js raw on github %}
  17. function array_multisort(arr) {
  18. // discuss at: http://phpjs.org/functions/array_multisort/
  19. // original by: Theriault
  20. // example 1: array_multisort([1, 2, 1, 2, 1, 2], [1, 2, 3, 4, 5, 6]);
  21. // returns 1: true
  22. // example 2: characters = {A: 'Edward', B: 'Locke', C: 'Sabin', D: 'Terra', E: 'Edward'};
  23. // example 2: jobs = {A: 'Warrior', B: 'Thief', C: 'Monk', D: 'Mage', E: 'Knight'};
  24. // example 2: array_multisort(characters, 'SORT_DESC', 'SORT_STRING', jobs, 'SORT_ASC', 'SORT_STRING');
  25. // returns 2: true
  26. // example 3: lastnames = [ 'Carter','Adams','Monroe','Tyler','Madison','Kennedy','Adams'];
  27. // example 3: firstnames = ['James', 'John' ,'James', 'John', 'James', 'John', 'John'];
  28. // example 3: president = [ 39, 6, 5, 10, 4, 35, 2 ];
  29. // example 3: array_multisort(firstnames, 'SORT_DESC', 'SORT_STRING', lastnames, 'SORT_ASC', 'SORT_STRING', president, 'SORT_NUMERIC');
  30. // returns 3: true
  31. // flags: Translation table for sort arguments. Each argument turns on certain bits in the flag byte through addition.
  32. // bits: HGFE DCBA
  33. // args: Holds pointer to arguments for reassignment
  34. var g, i, j, k, l, sal, vkey, elIndex, lastSorts, tmpArray, zlast;
  35. var sortFlag = [0];
  36. var thingsToSort = [];
  37. var nLastSort = [];
  38. var lastSort = [];
  39. var args = arguments; // possibly redundant
  40. var flags = {
  41. 'SORT_REGULAR': 16,
  42. 'SORT_NUMERIC': 17,
  43. 'SORT_STRING': 18,
  44. 'SORT_ASC': 32,
  45. 'SORT_DESC': 40
  46. };
  47. var sortDuplicator = function(a, b) {
  48. return nLastSort.shift();
  49. };
  50. var sortFunctions = [
  51. [
  52. function(a, b) {
  53. lastSort.push(a > b ? 1 : (a < b ? -1 : 0));
  54. return a > b ? 1 : (a < b ? -1 : 0);
  55. },
  56. function(a, b) {
  57. lastSort.push(b > a ? 1 : (b < a ? -1 : 0));
  58. return b > a ? 1 : (b < a ? -1 : 0);
  59. }
  60. ],
  61. [
  62. function(a, b) {
  63. lastSort.push(a - b);
  64. return a - b;
  65. },
  66. function(a, b) {
  67. lastSort.push(b - a);
  68. return b - a;
  69. }
  70. ],
  71. [
  72. function(a, b) {
  73. lastSort.push((a + '') > (b + '') ? 1 : ((a + '') < (b + '') ? -1 : 0));
  74. return (a + '') > (b + '') ? 1 : ((a + '') < (b + '') ? -1 : 0);
  75. },
  76. function(a, b) {
  77. lastSort.push((b + '') > (a + '') ? 1 : ((b + '') < (a + '') ? -1 : 0));
  78. return (b + '') > (a + '') ? 1 : ((b + '') < (a + '') ? -1 : 0);
  79. }
  80. ]
  81. ];
  82. var sortArrs = [
  83. []
  84. ];
  85. var sortKeys = [
  86. []
  87. ];
  88. // Store first argument into sortArrs and sortKeys if an Object.
  89. // First Argument should be either a Javascript Array or an Object, otherwise function would return FALSE like in PHP
  90. if (Object.prototype.toString.call(arr) === '[object Array]') {
  91. sortArrs[0] = arr;
  92. } else if (arr && typeof arr === 'object') {
  93. for (i in arr) {
  94. if (arr.hasOwnProperty(i)) {
  95. sortKeys[0].push(i);
  96. sortArrs[0].push(arr[i]);
  97. }
  98. }
  99. } else {
  100. return false;
  101. }
  102. // arrMainLength: Holds the length of the first array. All other arrays must be of equal length, otherwise function would return FALSE like in PHP
  103. //
  104. // sortComponents: Holds 2 indexes per every section of the array that can be sorted. As this is the start, the whole array can be sorted.
  105. var arrMainLength = sortArrs[0].length;
  106. var sortComponents = [0, arrMainLength];
  107. // Loop through all other arguments, checking lengths and sort flags of arrays and adding them to the above variables.
  108. var argl = arguments.length;
  109. for (j = 1; j < argl; j++) {
  110. if (Object.prototype.toString.call(arguments[j]) === '[object Array]') {
  111. sortArrs[j] = arguments[j];
  112. sortFlag[j] = 0;
  113. if (arguments[j].length !== arrMainLength) {
  114. return false;
  115. }
  116. } else if (arguments[j] && typeof arguments[j] === 'object') {
  117. sortKeys[j] = [];
  118. sortArrs[j] = [];
  119. sortFlag[j] = 0;
  120. for (i in arguments[j]) {
  121. if (arguments[j].hasOwnProperty(i)) {
  122. sortKeys[j].push(i);
  123. sortArrs[j].push(arguments[j][i]);
  124. }
  125. }
  126. if (sortArrs[j].length !== arrMainLength) {
  127. return false;
  128. }
  129. } else if (typeof arguments[j] === 'string') {
  130. var lFlag = sortFlag.pop();
  131. // Keep extra parentheses around latter flags check to avoid minimization leading to CDATA closer
  132. if (typeof flags[arguments[j]] === 'undefined' || ((((flags[arguments[j]]) >>> 4) & (lFlag >>> 4)) > 0)) {
  133. return false;
  134. }
  135. sortFlag.push(lFlag + flags[arguments[j]]);
  136. } else {
  137. return false;
  138. }
  139. }
  140. for (i = 0; i !== arrMainLength; i++) {
  141. thingsToSort.push(true);
  142. }
  143. // Sort all the arrays....
  144. for (i in sortArrs) {
  145. if (sortArrs.hasOwnProperty(i)) {
  146. lastSorts = [];
  147. tmpArray = [];
  148. elIndex = 0;
  149. nLastSort = [];
  150. lastSort = [];
  151. // If there are no sortComponents, then no more sorting is neeeded. Copy the array back to the argument.
  152. if (sortComponents.length === 0) {
  153. if (Object.prototype.toString.call(arguments[i]) === '[object Array]') {
  154. args[i] = sortArrs[i];
  155. } else {
  156. for (k in arguments[i]) {
  157. if (arguments[i].hasOwnProperty(k)) {
  158. delete arguments[i][k];
  159. }
  160. }
  161. sal = sortArrs[i].length;
  162. for (j = 0, vkey = 0; j < sal; j++) {
  163. vkey = sortKeys[i][j];
  164. args[i][vkey] = sortArrs[i][j];
  165. }
  166. }
  167. delete sortArrs[i];
  168. delete sortKeys[i];
  169. continue;
  170. }
  171. // Sort function for sorting. Either sorts asc or desc, regular/string or numeric.
  172. var sFunction = sortFunctions[(sortFlag[i] & 3)][((sortFlag[i] & 8) > 0) ? 1 : 0];
  173. // Sort current array.
  174. for (l = 0; l !== sortComponents.length; l += 2) {
  175. tmpArray = sortArrs[i].slice(sortComponents[l], sortComponents[l + 1] + 1);
  176. tmpArray.sort(sFunction);
  177. lastSorts[l] = [].concat(lastSort); // Is there a better way to copy an array in Javascript?
  178. elIndex = sortComponents[l];
  179. for (g in tmpArray) {
  180. if (tmpArray.hasOwnProperty(g)) {
  181. sortArrs[i][elIndex] = tmpArray[g];
  182. elIndex++;
  183. }
  184. }
  185. }
  186. // Duplicate the sorting of the current array on future arrays.
  187. sFunction = sortDuplicator;
  188. for (j in sortArrs) {
  189. if (sortArrs.hasOwnProperty(j)) {
  190. if (sortArrs[j] === sortArrs[i]) {
  191. continue;
  192. }
  193. for (l = 0; l !== sortComponents.length; l += 2) {
  194. tmpArray = sortArrs[j].slice(sortComponents[l], sortComponents[l + 1] + 1);
  195. nLastSort = [].concat(lastSorts[l]); // alert(l + ':' + nLastSort);
  196. tmpArray.sort(sFunction);
  197. elIndex = sortComponents[l];
  198. for (g in tmpArray) {
  199. if (tmpArray.hasOwnProperty(g)) {
  200. sortArrs[j][elIndex] = tmpArray[g];
  201. elIndex++;
  202. }
  203. }
  204. }
  205. }
  206. }
  207. // Duplicate the sorting of the current array on array keys
  208. for (j in sortKeys) {
  209. if (sortKeys.hasOwnProperty(j)) {
  210. for (l = 0; l !== sortComponents.length; l += 2) {
  211. tmpArray = sortKeys[j].slice(sortComponents[l], sortComponents[l + 1] + 1);
  212. nLastSort = [].concat(lastSorts[l]);
  213. tmpArray.sort(sFunction);
  214. elIndex = sortComponents[l];
  215. for (g in tmpArray) {
  216. if (tmpArray.hasOwnProperty(g)) {
  217. sortKeys[j][elIndex] = tmpArray[g];
  218. elIndex++;
  219. }
  220. }
  221. }
  222. }
  223. }
  224. // Generate the next sortComponents
  225. zlast = null;
  226. sortComponents = [];
  227. for (j in sortArrs[i]) {
  228. if (sortArrs[i].hasOwnProperty(j)) {
  229. if (!thingsToSort[j]) {
  230. if ((sortComponents.length & 1)) {
  231. sortComponents.push(j - 1);
  232. }
  233. zlast = null;
  234. continue;
  235. }
  236. if (!(sortComponents.length & 1)) {
  237. if (zlast !== null) {
  238. if (sortArrs[i][j] === zlast) {
  239. sortComponents.push(j - 1);
  240. } else {
  241. thingsToSort[j] = false;
  242. }
  243. }
  244. zlast = sortArrs[i][j];
  245. } else {
  246. if (sortArrs[i][j] !== zlast) {
  247. sortComponents.push(j - 1);
  248. zlast = sortArrs[i][j];
  249. }
  250. }
  251. }
  252. }
  253. if (sortComponents.length & 1) {
  254. sortComponents.push(j);
  255. }
  256. if (Object.prototype.toString.call(arguments[i]) === '[object Array]') {
  257. args[i] = sortArrs[i];
  258. } else {
  259. for (j in arguments[i]) {
  260. if (arguments[i].hasOwnProperty(j)) {
  261. delete arguments[i][j];
  262. }
  263. }
  264. sal = sortArrs[i].length;
  265. for (j = 0, vkey = 0; j < sal; j++) {
  266. vkey = sortKeys[i][j];
  267. args[i][vkey] = sortArrs[i][j];
  268. }
  269. }
  270. delete sortArrs[i];
  271. delete sortKeys[i];
  272. }
  273. }
  274. return true;
  275. }
  276. {% endcodeblock %}
  277. - [Raw function on GitHub](https://github.com/kvz/phpjs/blob/master/functions/array/array_multisort.js)
  278. Please note that php.js uses JavaScript objects as substitutes for PHP arrays, they are
  279. the closest match to this hashtable-like data structure.
  280. Please also note that php.js offers community built functions and goes by the
  281. [McDonald's Theory](https://medium.com/what-i-learned-building/9216e1c9da7d). We'll put online
  282. functions that are far from perfect, in the hopes to spark better contributions.
  283. Do you have one? Then please just:
  284. - [Edit on GitHub](https://github.com/kvz/phpjs/edit/master/functions/array/array_multisort.js)
  285. ### Other PHP functions in the array extension
  286. {% render_partial _includes/custom/array.html %}