min-dash.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  3. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  4. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MinDash = {}));
  5. }(this, (function (exports) { 'use strict';
  6. /**
  7. * Flatten array, one level deep.
  8. *
  9. * @param {Array<?>} arr
  10. *
  11. * @return {Array<?>}
  12. */
  13. function flatten(arr) {
  14. return Array.prototype.concat.apply([], arr);
  15. }
  16. var nativeToString = Object.prototype.toString;
  17. var nativeHasOwnProperty = Object.prototype.hasOwnProperty;
  18. function isUndefined(obj) {
  19. return obj === undefined;
  20. }
  21. function isDefined(obj) {
  22. return obj !== undefined;
  23. }
  24. function isNil(obj) {
  25. return obj == null;
  26. }
  27. function isArray(obj) {
  28. return nativeToString.call(obj) === '[object Array]';
  29. }
  30. function isObject(obj) {
  31. return nativeToString.call(obj) === '[object Object]';
  32. }
  33. function isNumber(obj) {
  34. return nativeToString.call(obj) === '[object Number]';
  35. }
  36. function isFunction(obj) {
  37. var tag = nativeToString.call(obj);
  38. return tag === '[object Function]' || tag === '[object AsyncFunction]' || tag === '[object GeneratorFunction]' || tag === '[object AsyncGeneratorFunction]' || tag === '[object Proxy]';
  39. }
  40. function isString(obj) {
  41. return nativeToString.call(obj) === '[object String]';
  42. }
  43. /**
  44. * Ensure collection is an array.
  45. *
  46. * @param {Object} obj
  47. */
  48. function ensureArray(obj) {
  49. if (isArray(obj)) {
  50. return;
  51. }
  52. throw new Error('must supply array');
  53. }
  54. /**
  55. * Return true, if target owns a property with the given key.
  56. *
  57. * @param {Object} target
  58. * @param {String} key
  59. *
  60. * @return {Boolean}
  61. */
  62. function has(target, key) {
  63. return nativeHasOwnProperty.call(target, key);
  64. }
  65. /**
  66. * Find element in collection.
  67. *
  68. * @param {Array|Object} collection
  69. * @param {Function|Object} matcher
  70. *
  71. * @return {Object}
  72. */
  73. function find(collection, matcher) {
  74. matcher = toMatcher(matcher);
  75. var match;
  76. forEach(collection, function (val, key) {
  77. if (matcher(val, key)) {
  78. match = val;
  79. return false;
  80. }
  81. });
  82. return match;
  83. }
  84. /**
  85. * Find element index in collection.
  86. *
  87. * @param {Array|Object} collection
  88. * @param {Function} matcher
  89. *
  90. * @return {Object}
  91. */
  92. function findIndex(collection, matcher) {
  93. matcher = toMatcher(matcher);
  94. var idx = isArray(collection) ? -1 : undefined;
  95. forEach(collection, function (val, key) {
  96. if (matcher(val, key)) {
  97. idx = key;
  98. return false;
  99. }
  100. });
  101. return idx;
  102. }
  103. /**
  104. * Find element in collection.
  105. *
  106. * @param {Array|Object} collection
  107. * @param {Function} matcher
  108. *
  109. * @return {Array} result
  110. */
  111. function filter(collection, matcher) {
  112. var result = [];
  113. forEach(collection, function (val, key) {
  114. if (matcher(val, key)) {
  115. result.push(val);
  116. }
  117. });
  118. return result;
  119. }
  120. /**
  121. * Iterate over collection; returning something
  122. * (non-undefined) will stop iteration.
  123. *
  124. * @param {Array|Object} collection
  125. * @param {Function} iterator
  126. *
  127. * @return {Object} return result that stopped the iteration
  128. */
  129. function forEach(collection, iterator) {
  130. var val, result;
  131. if (isUndefined(collection)) {
  132. return;
  133. }
  134. var convertKey = isArray(collection) ? toNum : identity;
  135. for (var key in collection) {
  136. if (has(collection, key)) {
  137. val = collection[key];
  138. result = iterator(val, convertKey(key));
  139. if (result === false) {
  140. return val;
  141. }
  142. }
  143. }
  144. }
  145. /**
  146. * Return collection without element.
  147. *
  148. * @param {Array} arr
  149. * @param {Function} matcher
  150. *
  151. * @return {Array}
  152. */
  153. function without(arr, matcher) {
  154. if (isUndefined(arr)) {
  155. return [];
  156. }
  157. ensureArray(arr);
  158. matcher = toMatcher(matcher);
  159. return arr.filter(function (el, idx) {
  160. return !matcher(el, idx);
  161. });
  162. }
  163. /**
  164. * Reduce collection, returning a single result.
  165. *
  166. * @param {Object|Array} collection
  167. * @param {Function} iterator
  168. * @param {Any} result
  169. *
  170. * @return {Any} result returned from last iterator
  171. */
  172. function reduce(collection, iterator, result) {
  173. forEach(collection, function (value, idx) {
  174. result = iterator(result, value, idx);
  175. });
  176. return result;
  177. }
  178. /**
  179. * Return true if every element in the collection
  180. * matches the criteria.
  181. *
  182. * @param {Object|Array} collection
  183. * @param {Function} matcher
  184. *
  185. * @return {Boolean}
  186. */
  187. function every(collection, matcher) {
  188. return !!reduce(collection, function (matches, val, key) {
  189. return matches && matcher(val, key);
  190. }, true);
  191. }
  192. /**
  193. * Return true if some elements in the collection
  194. * match the criteria.
  195. *
  196. * @param {Object|Array} collection
  197. * @param {Function} matcher
  198. *
  199. * @return {Boolean}
  200. */
  201. function some(collection, matcher) {
  202. return !!find(collection, matcher);
  203. }
  204. /**
  205. * Transform a collection into another collection
  206. * by piping each member through the given fn.
  207. *
  208. * @param {Object|Array} collection
  209. * @param {Function} fn
  210. *
  211. * @return {Array} transformed collection
  212. */
  213. function map(collection, fn) {
  214. var result = [];
  215. forEach(collection, function (val, key) {
  216. result.push(fn(val, key));
  217. });
  218. return result;
  219. }
  220. /**
  221. * Get the collections keys.
  222. *
  223. * @param {Object|Array} collection
  224. *
  225. * @return {Array}
  226. */
  227. function keys(collection) {
  228. return collection && Object.keys(collection) || [];
  229. }
  230. /**
  231. * Shorthand for `keys(o).length`.
  232. *
  233. * @param {Object|Array} collection
  234. *
  235. * @return {Number}
  236. */
  237. function size(collection) {
  238. return keys(collection).length;
  239. }
  240. /**
  241. * Get the values in the collection.
  242. *
  243. * @param {Object|Array} collection
  244. *
  245. * @return {Array}
  246. */
  247. function values(collection) {
  248. return map(collection, function (val) {
  249. return val;
  250. });
  251. }
  252. /**
  253. * Group collection members by attribute.
  254. *
  255. * @param {Object|Array} collection
  256. * @param {Function} extractor
  257. *
  258. * @return {Object} map with { attrValue => [ a, b, c ] }
  259. */
  260. function groupBy(collection, extractor) {
  261. var grouped = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  262. extractor = toExtractor(extractor);
  263. forEach(collection, function (val) {
  264. var discriminator = extractor(val) || '_';
  265. var group = grouped[discriminator];
  266. if (!group) {
  267. group = grouped[discriminator] = [];
  268. }
  269. group.push(val);
  270. });
  271. return grouped;
  272. }
  273. function uniqueBy(extractor) {
  274. extractor = toExtractor(extractor);
  275. var grouped = {};
  276. for (var _len = arguments.length, collections = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  277. collections[_key - 1] = arguments[_key];
  278. }
  279. forEach(collections, function (c) {
  280. return groupBy(c, extractor, grouped);
  281. });
  282. var result = map(grouped, function (val, key) {
  283. return val[0];
  284. });
  285. return result;
  286. }
  287. var unionBy = uniqueBy;
  288. /**
  289. * Sort collection by criteria.
  290. *
  291. * @param {Object|Array} collection
  292. * @param {String|Function} extractor
  293. *
  294. * @return {Array}
  295. */
  296. function sortBy(collection, extractor) {
  297. extractor = toExtractor(extractor);
  298. var sorted = [];
  299. forEach(collection, function (value, key) {
  300. var disc = extractor(value, key);
  301. var entry = {
  302. d: disc,
  303. v: value
  304. };
  305. for (var idx = 0; idx < sorted.length; idx++) {
  306. var d = sorted[idx].d;
  307. if (disc < d) {
  308. sorted.splice(idx, 0, entry);
  309. return;
  310. }
  311. } // not inserted, append (!)
  312. sorted.push(entry);
  313. });
  314. return map(sorted, function (e) {
  315. return e.v;
  316. });
  317. }
  318. /**
  319. * Create an object pattern matcher.
  320. *
  321. * @example
  322. *
  323. * const matcher = matchPattern({ id: 1 });
  324. *
  325. * let element = find(elements, matcher);
  326. *
  327. * @param {Object} pattern
  328. *
  329. * @return {Function} matcherFn
  330. */
  331. function matchPattern(pattern) {
  332. return function (el) {
  333. return every(pattern, function (val, key) {
  334. return el[key] === val;
  335. });
  336. };
  337. }
  338. function toExtractor(extractor) {
  339. return isFunction(extractor) ? extractor : function (e) {
  340. return e[extractor];
  341. };
  342. }
  343. function toMatcher(matcher) {
  344. return isFunction(matcher) ? matcher : function (e) {
  345. return e === matcher;
  346. };
  347. }
  348. function identity(arg) {
  349. return arg;
  350. }
  351. function toNum(arg) {
  352. return Number(arg);
  353. }
  354. /**
  355. * Debounce fn, calling it only once if the given time
  356. * elapsed between calls.
  357. *
  358. * Lodash-style the function exposes methods to `#clear`
  359. * and `#flush` to control internal behavior.
  360. *
  361. * @param {Function} fn
  362. * @param {Number} timeout
  363. *
  364. * @return {Function} debounced function
  365. */
  366. function debounce(fn, timeout) {
  367. var timer;
  368. var lastArgs;
  369. var lastThis;
  370. var lastNow;
  371. function fire(force) {
  372. var now = Date.now();
  373. var scheduledDiff = force ? 0 : lastNow + timeout - now;
  374. if (scheduledDiff > 0) {
  375. return schedule(scheduledDiff);
  376. }
  377. fn.apply(lastThis, lastArgs);
  378. clear();
  379. }
  380. function schedule(timeout) {
  381. timer = setTimeout(fire, timeout);
  382. }
  383. function clear() {
  384. if (timer) {
  385. clearTimeout(timer);
  386. }
  387. timer = lastNow = lastArgs = lastThis = undefined;
  388. }
  389. function flush() {
  390. if (timer) {
  391. fire(true);
  392. }
  393. clear();
  394. }
  395. function callback() {
  396. lastNow = Date.now();
  397. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  398. args[_key] = arguments[_key];
  399. }
  400. lastArgs = args;
  401. lastThis = this; // ensure an execution is scheduled
  402. if (!timer) {
  403. schedule(timeout);
  404. }
  405. }
  406. callback.flush = flush;
  407. callback.cancel = clear;
  408. return callback;
  409. }
  410. /**
  411. * Throttle fn, calling at most once
  412. * in the given interval.
  413. *
  414. * @param {Function} fn
  415. * @param {Number} interval
  416. *
  417. * @return {Function} throttled function
  418. */
  419. function throttle(fn, interval) {
  420. var throttling = false;
  421. return function () {
  422. if (throttling) {
  423. return;
  424. }
  425. fn.apply(void 0, arguments);
  426. throttling = true;
  427. setTimeout(function () {
  428. throttling = false;
  429. }, interval);
  430. };
  431. }
  432. /**
  433. * Bind function against target <this>.
  434. *
  435. * @param {Function} fn
  436. * @param {Object} target
  437. *
  438. * @return {Function} bound function
  439. */
  440. function bind(fn, target) {
  441. return fn.bind(target);
  442. }
  443. function _typeof(obj) {
  444. "@babel/helpers - typeof";
  445. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  446. _typeof = function (obj) {
  447. return typeof obj;
  448. };
  449. } else {
  450. _typeof = function (obj) {
  451. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  452. };
  453. }
  454. return _typeof(obj);
  455. }
  456. function _extends() {
  457. _extends = Object.assign || function (target) {
  458. for (var i = 1; i < arguments.length; i++) {
  459. var source = arguments[i];
  460. for (var key in source) {
  461. if (Object.prototype.hasOwnProperty.call(source, key)) {
  462. target[key] = source[key];
  463. }
  464. }
  465. }
  466. return target;
  467. };
  468. return _extends.apply(this, arguments);
  469. }
  470. /**
  471. * Convenience wrapper for `Object.assign`.
  472. *
  473. * @param {Object} target
  474. * @param {...Object} others
  475. *
  476. * @return {Object} the target
  477. */
  478. function assign(target) {
  479. for (var _len = arguments.length, others = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  480. others[_key - 1] = arguments[_key];
  481. }
  482. return _extends.apply(void 0, [target].concat(others));
  483. }
  484. /**
  485. * Sets a nested property of a given object to the specified value.
  486. *
  487. * This mutates the object and returns it.
  488. *
  489. * @param {Object} target The target of the set operation.
  490. * @param {(string|number)[]} path The path to the nested value.
  491. * @param {any} value The value to set.
  492. */
  493. function set(target, path, value) {
  494. var currentTarget = target;
  495. forEach(path, function (key, idx) {
  496. if (typeof key !== 'number' && typeof key !== 'string') {
  497. throw new Error('illegal key type: ' + _typeof(key) + '. Key should be of type number or string.');
  498. }
  499. if (key === 'constructor') {
  500. throw new Error('illegal key: constructor');
  501. }
  502. if (key === '__proto__') {
  503. throw new Error('illegal key: __proto__');
  504. }
  505. var nextKey = path[idx + 1];
  506. var nextTarget = currentTarget[key];
  507. if (isDefined(nextKey) && isNil(nextTarget)) {
  508. nextTarget = currentTarget[key] = isNaN(+nextKey) ? {} : [];
  509. }
  510. if (isUndefined(nextKey)) {
  511. if (isUndefined(value)) {
  512. delete currentTarget[key];
  513. } else {
  514. currentTarget[key] = value;
  515. }
  516. } else {
  517. currentTarget = nextTarget;
  518. }
  519. });
  520. return target;
  521. }
  522. /**
  523. * Gets a nested property of a given object.
  524. *
  525. * @param {Object} target The target of the get operation.
  526. * @param {(string|number)[]} path The path to the nested value.
  527. * @param {any} [defaultValue] The value to return if no value exists.
  528. */
  529. function get(target, path, defaultValue) {
  530. var currentTarget = target;
  531. forEach(path, function (key) {
  532. // accessing nil property yields <undefined>
  533. if (isNil(currentTarget)) {
  534. currentTarget = undefined;
  535. return false;
  536. }
  537. currentTarget = currentTarget[key];
  538. });
  539. return isUndefined(currentTarget) ? defaultValue : currentTarget;
  540. }
  541. /**
  542. * Pick given properties from the target object.
  543. *
  544. * @param {Object} target
  545. * @param {Array} properties
  546. *
  547. * @return {Object} target
  548. */
  549. function pick(target, properties) {
  550. var result = {};
  551. var obj = Object(target);
  552. forEach(properties, function (prop) {
  553. if (prop in obj) {
  554. result[prop] = target[prop];
  555. }
  556. });
  557. return result;
  558. }
  559. /**
  560. * Pick all target properties, excluding the given ones.
  561. *
  562. * @param {Object} target
  563. * @param {Array} properties
  564. *
  565. * @return {Object} target
  566. */
  567. function omit(target, properties) {
  568. var result = {};
  569. var obj = Object(target);
  570. forEach(obj, function (prop, key) {
  571. if (properties.indexOf(key) === -1) {
  572. result[key] = prop;
  573. }
  574. });
  575. return result;
  576. }
  577. /**
  578. * Recursively merge `...sources` into given target.
  579. *
  580. * Does support merging objects; does not support merging arrays.
  581. *
  582. * @param {Object} target
  583. * @param {...Object} sources
  584. *
  585. * @return {Object} the target
  586. */
  587. function merge(target) {
  588. for (var _len2 = arguments.length, sources = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  589. sources[_key2 - 1] = arguments[_key2];
  590. }
  591. if (!sources.length) {
  592. return target;
  593. }
  594. forEach(sources, function (source) {
  595. // skip non-obj sources, i.e. null
  596. if (!source || !isObject(source)) {
  597. return;
  598. }
  599. forEach(source, function (sourceVal, key) {
  600. if (key === '__proto__') {
  601. return;
  602. }
  603. var targetVal = target[key];
  604. if (isObject(sourceVal)) {
  605. if (!isObject(targetVal)) {
  606. // override target[key] with object
  607. targetVal = {};
  608. }
  609. target[key] = merge(targetVal, sourceVal);
  610. } else {
  611. target[key] = sourceVal;
  612. }
  613. });
  614. });
  615. return target;
  616. }
  617. exports.assign = assign;
  618. exports.bind = bind;
  619. exports.debounce = debounce;
  620. exports.ensureArray = ensureArray;
  621. exports.every = every;
  622. exports.filter = filter;
  623. exports.find = find;
  624. exports.findIndex = findIndex;
  625. exports.flatten = flatten;
  626. exports.forEach = forEach;
  627. exports.get = get;
  628. exports.groupBy = groupBy;
  629. exports.has = has;
  630. exports.isArray = isArray;
  631. exports.isDefined = isDefined;
  632. exports.isFunction = isFunction;
  633. exports.isNil = isNil;
  634. exports.isNumber = isNumber;
  635. exports.isObject = isObject;
  636. exports.isString = isString;
  637. exports.isUndefined = isUndefined;
  638. exports.keys = keys;
  639. exports.map = map;
  640. exports.matchPattern = matchPattern;
  641. exports.merge = merge;
  642. exports.omit = omit;
  643. exports.pick = pick;
  644. exports.reduce = reduce;
  645. exports.set = set;
  646. exports.size = size;
  647. exports.some = some;
  648. exports.sortBy = sortBy;
  649. exports.throttle = throttle;
  650. exports.unionBy = unionBy;
  651. exports.uniqueBy = uniqueBy;
  652. exports.values = values;
  653. exports.without = without;
  654. Object.defineProperty(exports, '__esModule', { value: true });
  655. })));