Difference between revisions of "Template:SDU-Denmark/js/simple/app"

Line 18: Line 18:
 
mithril_1.default.route.prefix('');
 
mithril_1.default.route.prefix('');
 
if (!lodash_1.default.isNull(root)) {
 
if (!lodash_1.default.isNull(root)) {
     mithril_1.default.route(root, '/', {
+
     mithril_1.default.route(root, '/Team:SDU-Denmark/simple', {
 
         '/': Home_1.default,
 
         '/': Home_1.default,
 
         '/about': About_1.default
 
         '/about': About_1.default

Revision as of 17:07, 21 July 2019

(function(FuseBox){FuseBox.$fuse$=FuseBox; FuseBox.target = "browser"; // allowSyntheticDefaultImports FuseBox.sdep = true; FuseBox.pkg("default", {}, function(___scope___){ ___scope___.file("main.js", function(exports, require, module, __filename, __dirname){ /* fuse:injection: */ var process = require("process"); "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const mithril_1 = tslib_1.__importDefault(require("mithril")); const Home_1 = tslib_1.__importDefault(require("./components/Home")); const About_1 = tslib_1.__importDefault(require("./components/About")); const lodash_1 = tslib_1.__importDefault(require("lodash")); if (process.env.prod) { } const root = document.querySelector('#content'); mithril_1.default.route.prefix(); if (!lodash_1.default.isNull(root)) {

   mithril_1.default.route(root, '/Team:SDU-Denmark/simple', {
       '/': Home_1.default,
       '/about': About_1.default
   });

} else {

   console.error('No bootstrap element with ID #content');

}

}); ___scope___.file("components/Home.js", function(exports, require, module, __filename, __dirname){

"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const mithril_1 = tslib_1.__importDefault(require("mithril")); const Nav_1 = tslib_1.__importDefault(require("./Nav")); const Home = {

   view(vnode) {
       return mithril_1.default('.page', [
           mithril_1.default(Nav_1.default),
           mithril_1.default('h1', "Home")
       ]);
   },
   oncreate() {
       //debugger
   }

}; exports.default = Home;

}); ___scope___.file("components/Nav.js", function(exports, require, module, __filename, __dirname){

"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const mithril_1 = tslib_1.__importDefault(require("mithril")); const Nav = {

   view(vnode) {
       return mithril_1.default('div', mithril_1.default('a', { href: '/', oncreate: mithril_1.default.route.link }, "Home"), mithril_1.default('span', " | "), mithril_1.default('a', { href: '/about', oncreate: mithril_1.default.route.link }, "About"));
   }

}; exports.default = Nav;

}); ___scope___.file("components/About.js", function(exports, require, module, __filename, __dirname){

"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const mithril_1 = tslib_1.__importDefault(require("mithril")); const Nav_1 = tslib_1.__importDefault(require("./Nav")); const App = {

   view(vnode) {
       return mithril_1.default('.page', [
           mithril_1.default(Nav_1.default),
           mithril_1.default('h1', "About"),
           mithril_1.default('p', "This is the about page.")
       ]);
   }

}; exports.default = App;

}); return ___scope___.entry = "main.js"; }); FuseBox.pkg("events", {}, function(___scope___){ ___scope___.file("index.js", function(exports, require, module, __filename, __dirname){

// Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. if (FuseBox.isServer) { module.exports = global.require("events"); } else { function EventEmitter() { this._events = this._events || {}; this._maxListeners = this._maxListeners || undefined; } module.exports = EventEmitter;

// Backwards-compat with node 0.10.x EventEmitter.EventEmitter = EventEmitter;

EventEmitter.prototype._events = undefined; EventEmitter.prototype._maxListeners = undefined;

// By default EventEmitters will print a warning if more than 10 listeners are // added to it. This is a useful default which helps finding memory leaks. EventEmitter.defaultMaxListeners = 10;

// Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function(n) { if (!isNumber(n) || n < 0 || isNaN(n)) throw TypeError("n must be a positive number"); this._maxListeners = n; return this; };

EventEmitter.prototype.emit = function(type) { var er, handler, len, args, i, listeners;

if (!this._events) this._events = {};

// If there is no 'error' event listener then throw. if (type === "error") { if (!this._events.error || (isObject(this._events.error) && !this._events.error.length)) { er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event } throw TypeError('Uncaught, unspecified "error" event.'); } }

handler = this._events[type];

if (isUndefined(handler)) return false;

if (isFunction(handler)) { switch (arguments.length) { // fast cases case 1: handler.call(this); break; case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: args = Array.prototype.slice.call(arguments, 1); handler.apply(this, args); } } else if (isObject(handler)) { args = Array.prototype.slice.call(arguments, 1); listeners = handler.slice(); len = listeners.length; for (i = 0; i < len; i++) listeners[i].apply(this, args); }

return true; };

EventEmitter.prototype.addListener = function(type, listener) { var m;

if (!isFunction(listener)) throw TypeError("listener must be a function");

if (!this._events) this._events = {};

// To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (this._events.newListener) this.emit("newListener", type, isFunction(listener.listener) ? listener.listener : listener);

if (!this._events[type]) // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; else if (isObject(this._events[type])) // If we've already got an array, just append. this._events[type].push(listener); // Adding the second element, need to change to array. else this._events[type] = [this._events[type], listener];

// Check for listener leak if (isObject(this._events[type]) && !this._events[type].warned) { if (!isUndefined(this._maxListeners)) { m = this._maxListeners; } else { m = EventEmitter.defaultMaxListeners; }

if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error( "(node) warning: possible EventEmitter memory " + "leak detected. %d listeners added. " + "Use emitter.setMaxListeners() to increase limit.", this._events[type].length ); if (typeof console.trace === "function") { // not supported in IE 10 console.trace(); } } }

return this; };

EventEmitter.prototype.on = EventEmitter.prototype.addListener;

EventEmitter.prototype.once = function(type, listener) { if (!isFunction(listener)) throw TypeError("listener must be a function");

var fired = false;

function g() { this.removeListener(type, g);

if (!fired) { fired = true; listener.apply(this, arguments); } }

g.listener = listener; this.on(type, g);

return this; };

// emits a 'removeListener' event iff the listener was removed EventEmitter.prototype.removeListener = function(type, listener) { var list, position, length, i;

if (!isFunction(listener)) throw TypeError("listener must be a function");

if (!this._events || !this._events[type]) return this;

list = this._events[type]; length = list.length; position = -1;

if (list === listener || (isFunction(list.listener) && list.listener === listener)) { delete this._events[type]; if (this._events.removeListener) this.emit("removeListener", type, listener); } else if (isObject(list)) { for (i = length; i-- > 0; ) { if (list[i] === listener || (list[i].listener && list[i].listener === listener)) { position = i; break; } }

if (position < 0) return this;

if (list.length === 1) { list.length = 0; delete this._events[type]; } else { list.splice(position, 1); }

if (this._events.removeListener) this.emit("removeListener", type, listener); }

return this; };

EventEmitter.prototype.removeAllListeners = function(type) { var key, listeners;

if (!this._events) return this;

// not listening for removeListener, no need to emit if (!this._events.removeListener) { if (arguments.length === 0) this._events = {}; else if (this._events[type]) delete this._events[type]; return this; }

// emit removeListener for all listeners on all events if (arguments.length === 0) { for (key in this._events) { if (key === "removeListener") continue; this.removeAllListeners(key); } this.removeAllListeners("removeListener"); this._events = {}; return this; }

listeners = this._events[type];

if (isFunction(listeners)) { this.removeListener(type, listeners); } else if (listeners) { // LIFO order while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); } delete this._events[type];

return this; };

EventEmitter.prototype.listeners = function(type) { var ret; if (!this._events || !this._events[type]) ret = []; else if (isFunction(this._events[type])) ret = [this._events[type]]; else ret = this._events[type].slice(); return ret; };

EventEmitter.prototype.listenerCount = function(type) { if (this._events) { var evlistener = this._events[type];

if (isFunction(evlistener)) return 1; else if (evlistener) return evlistener.length; } return 0; };

EventEmitter.listenerCount = function(emitter, type) { return emitter.listenerCount(type); };

function isFunction(arg) { return typeof arg === "function"; }

function isNumber(arg) { return typeof arg === "number"; }

function isObject(arg) { return typeof arg === "object" && arg !== null; }

function isUndefined(arg) { return arg === void 0; } }

}); return ___scope___.entry = "index.js"; }); FuseBox.pkg("fusebox-hot-reload", {}, function(___scope___){ ___scope___.file("index.js", function(exports, require, module, __filename, __dirname){

"use strict"; /**

* @module listens to `source-changed` socket events and actions hot reload
*/

Object.defineProperty(exports, "__esModule", { value: true }); var Client = require("fusebox-websocket").SocketClient, bundleErrors = {}, outputElement = document.createElement("div"), styleElement = document.createElement("style"), minimizeToggleId = "fuse-box-toggle-minimized", hideButtonId = "fuse-box-hide", expandedOutputClass = "fuse-box-expanded-output", localStoragePrefix = "__fuse-box_"; function storeSetting(key, value) {

   localStorage[localStoragePrefix + key] = value;

} function getSetting(key) {

   return localStorage[localStoragePrefix + key] === "true" ? true : false;

} var outputInBody = false, outputMinimized = getSetting(minimizeToggleId), outputHidden = false; outputElement.id = "fuse-box-output"; styleElement.innerHTML = "\n #" + outputElement.id + ", #" + outputElement.id + " * {\n box-sizing: border-box;\n }\n #" + outputElement.id + " {\n z-index: 999999999999;\n position: fixed;\n top: 10px;\n right: 10px;\n width: 400px;\n overflow: auto;\n background: #fdf3f1;\n border: 1px solid #eca494;\n border-radius: 5px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n box-shadow: 0px 3px 6px 1px rgba(0,0,0,.15);\n }\n #" + outputElement.id + "." + expandedOutputClass + " {\n height: auto;\n width: auto;\n left: 10px;\n max-height: calc(100vh - 50px);\n }\n #" + outputElement.id + " .fuse-box-errors {\n display: none;\n }\n #" + outputElement.id + "." + expandedOutputClass + " .fuse-box-errors {\n display: block;\n border-top: 1px solid #eca494;\n padding: 0 10px;\n }\n #" + outputElement.id + " button {\n border: 1px solid #eca494;\n padding: 5px 10px;\n border-radius: 4px;\n margin-left: 5px;\n background-color: white;\n color: black;\n box-shadow: 0px 2px 2px 0px rgba(0,0,0,.05);\n }\n #" + outputElement.id + " .fuse-box-header {\n padding: 10px;\n }\n #" + outputElement.id + " .fuse-box-header h4 {\n display: inline-block;\n margin: 4px;\n }"; styleElement.type = "text/css"; document.getElementsByTagName("head")[0].appendChild(styleElement); function displayBundleErrors() {

   var errorMessages = Object.keys(bundleErrors).reduce(function (allMessages, bundleName) {
       var bundleMessages = bundleErrors[bundleName];
       return allMessages.concat(bundleMessages.map(function (message) {
           var messageOutput = message
               .replace(/\n/g, "
") .replace(/\t/g, " &nbps;&npbs;&nbps;") .replace(/ /g, " ");
return "
" + messageOutput + "
";
       }));
   }, []), errorOutput = errorMessages.join("");
   if (errorOutput && !outputHidden) {
outputElement.innerHTML = "\n
\n

Fuse Box Bundle Errors (" + errorMessages.length + "):

\n
\n <button id=\"" + minimizeToggleId + "\">" + (outputMinimized ? "Expand" : "Minimize") + "</button>\n <button id=\"" + hideButtonId + "\">Hide</button>\n
\n
\n
\n " + errorOutput + "\n
\n ";
       document.body.appendChild(outputElement);
       outputElement.className = outputMinimized ? "" : expandedOutputClass;
       outputInBody = true;
       document.getElementById(minimizeToggleId).onclick = function () {
           outputMinimized = !outputMinimized;
           storeSetting(minimizeToggleId, outputMinimized);
           displayBundleErrors();
       };
       document.getElementById(hideButtonId).onclick = function () {
           outputHidden = true;
           displayBundleErrors();
       };
   }
   else if (outputInBody) {
       document.body.removeChild(outputElement);
       outputInBody = false;
   }

} exports.connect = function (port, uri, reloadFullPage) {

   if (FuseBox.isServer) {
       return;
   }
   port = port || window.location.port;
   var client = new Client({
       port: port,
       uri: uri
   });
   client.connect();
   client.on("page-reload", function (data) {
       return window.location.reload();
   });
   client.on("page-hmr", function (data) {
       FuseBox.flush();
       FuseBox.dynamic(data.path, data.content);
       if (FuseBox.mainFile) {
           try {
               FuseBox.import(FuseBox.mainFile);
           }
           catch (e) {
               if (typeof e === "string") {
                   if (/not found/.test(e)) {
                       return window.location.reload();
                   }
               }
               console.error(e);
           }
       }
   });
   client.on("source-changed", function (data) {
       console.info("%cupdate \"" + data.path + "\"", "color: #237abe");
       if (reloadFullPage) {
           return window.location.reload();
       }
       /**
        * If a plugin handles this request then we don't have to do anything
        **/
       for (var index = 0; index < FuseBox.plugins.length; index++) {
           var plugin = FuseBox.plugins[index];
           if (plugin.hmrUpdate && plugin.hmrUpdate(data)) {
               return;
           }
       }
       if (data.type === "hosted-css") {
           var fileId = data.path.replace(/^\//, "").replace(/[\.\/]+/g, "-");
           var existing = document.getElementById(fileId);
           if (existing) {
               existing.setAttribute("href", data.path + "?" + new Date().getTime());
           }
           else {
               var node = document.createElement("link");
               node.id = fileId;
               node.type = "text/css";
               node.rel = "stylesheet";
               node.href = data.path;
               document.getElementsByTagName("head")[0].appendChild(node);
           }
       }
       if (data.type === "js" || data.type === "css") {
           FuseBox.flush();
           FuseBox.dynamic(data.path, data.content);
           if (FuseBox.mainFile) {
               try {
                   FuseBox.import(FuseBox.mainFile);
               }
               catch (e) {
                   if (typeof e === "string") {
                       if (/not found/.test(e)) {
                           return window.location.reload();
                       }
                   }
                   console.error(e);
               }
           }
       }
   });
   client.on("error", function (error) {
       console.log(error);
   });
   client.on("bundle-error", function (_a) {
       var bundleName = _a.bundleName, message = _a.message;
       console.error("Bundle error in " + bundleName + ": " + message);
       var errorsForBundle = bundleErrors[bundleName] || [];
       errorsForBundle.push(message);
       bundleErrors[bundleName] = errorsForBundle;
       displayBundleErrors();
   });
   client.on("update-bundle-errors", function (_a) {
       var bundleName = _a.bundleName, messages = _a.messages;
       messages.forEach(function (message) { return console.error("Bundle error in " + bundleName + ": " + message); });
       bundleErrors[bundleName] = messages;
       displayBundleErrors();
   });

};

}); return ___scope___.entry = "index.js"; }); FuseBox.pkg("fusebox-websocket", {}, function(___scope___){ ___scope___.file("index.js", function(exports, require, module, __filename, __dirname){

"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var events = require("events"); var SocketClient = /** @class */ (function () {

   function SocketClient(opts) {
       opts = opts || {};
       var port = opts.port || window.location.port;
       var protocol = location.protocol === "https:" ? "wss://" : "ws://";
       var domain = location.hostname || "localhost";
       this.url = opts.host || "" + protocol + domain + ":" + port;
       if (opts.uri) {
           this.url = opts.uri;
       }
       this.authSent = false;
       this.emitter = new events.EventEmitter();
   }
   SocketClient.prototype.reconnect = function (fn) {
       var _this = this;
       setTimeout(function () {
           _this.emitter.emit("reconnect", { message: "Trying to reconnect" });
           _this.connect(fn);
       }, 5000);
   };
   SocketClient.prototype.on = function (event, fn) {
       this.emitter.on(event, fn);
   };
   SocketClient.prototype.connect = function (fn) {
       var _this = this;
       console.log("%cConnecting to fusebox HMR at " + this.url, "color: #237abe");
       setTimeout(function () {
           _this.client = new WebSocket(_this.url);
           _this.bindEvents(fn);
       }, 0);
   };
   SocketClient.prototype.close = function () {
       this.client.close();
   };
   SocketClient.prototype.send = function (eventName, data) {
       if (this.client.readyState === 1) {
           this.client.send(JSON.stringify({ event: eventName, data: data || {} }));
       }
   };
   SocketClient.prototype.error = function (data) {
       this.emitter.emit("error", data);
   };
   /** Wires up the socket client messages to be emitted on our event emitter */
   SocketClient.prototype.bindEvents = function (fn) {
       var _this = this;
       this.client.onopen = function (event) {
           console.log("%cConnected", "color: #237abe");
           if (fn) {
               fn(_this);
           }
       };
       this.client.onerror = function (event) {
           _this.error({ reason: event.reason, message: "Socket error" });
       };
       this.client.onclose = function (event) {
           _this.emitter.emit("close", { message: "Socket closed" });
           if (event.code !== 1011) {
               _this.reconnect(fn);
           }
       };
       this.client.onmessage = function (event) {
           var data = event.data;
           if (data) {
               var item = JSON.parse(data);
               _this.emitter.emit(item.type, item.data);
               _this.emitter.emit("*", item);
           }
       };
   };
   return SocketClient;

}()); exports.SocketClient = SocketClient;

}); return ___scope___.entry = "index.js"; }); FuseBox.pkg("lodash", {}, function(___scope___){ ___scope___.file("lodash.js", function(exports, require, module, __filename, __dirname){

/**

* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
(function() {
 /** Used as a safe reference for `undefined` in pre-ES5 environments. */
 var undefined;
 /** Used as the semantic version number. */
 var VERSION = '4.17.14';
 /** Used as the size to enable large array optimizations. */
 var LARGE_ARRAY_SIZE = 200;
 /** Error message constants. */
 var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
     FUNC_ERROR_TEXT = 'Expected a function';
 /** Used to stand-in for `undefined` hash values. */
 var HASH_UNDEFINED = '__lodash_hash_undefined__';
 /** Used as the maximum memoize cache size. */
 var MAX_MEMOIZE_SIZE = 500;
 /** Used as the internal argument placeholder. */
 var PLACEHOLDER = '__lodash_placeholder__';
 /** Used to compose bitmasks for cloning. */
 var CLONE_DEEP_FLAG = 1,
     CLONE_FLAT_FLAG = 2,
     CLONE_SYMBOLS_FLAG = 4;
 /** Used to compose bitmasks for value comparisons. */
 var COMPARE_PARTIAL_FLAG = 1,
     COMPARE_UNORDERED_FLAG = 2;
 /** Used to compose bitmasks for function metadata. */
 var WRAP_BIND_FLAG = 1,
     WRAP_BIND_KEY_FLAG = 2,
     WRAP_CURRY_BOUND_FLAG = 4,
     WRAP_CURRY_FLAG = 8,
     WRAP_CURRY_RIGHT_FLAG = 16,
     WRAP_PARTIAL_FLAG = 32,
     WRAP_PARTIAL_RIGHT_FLAG = 64,
     WRAP_ARY_FLAG = 128,
     WRAP_REARG_FLAG = 256,
     WRAP_FLIP_FLAG = 512;
 /** Used as default options for `_.truncate`. */
 var DEFAULT_TRUNC_LENGTH = 30,
     DEFAULT_TRUNC_OMISSION = '...';
 /** Used to detect hot functions by number of calls within a span of milliseconds. */
 var HOT_COUNT = 800,
     HOT_SPAN = 16;
 /** Used to indicate the type of lazy iteratees. */
 var LAZY_FILTER_FLAG = 1,
     LAZY_MAP_FLAG = 2,
     LAZY_WHILE_FLAG = 3;
 /** Used as references for various `Number` constants. */
 var INFINITY = 1 / 0,
     MAX_SAFE_INTEGER = 9007199254740991,
     MAX_INTEGER = 1.7976931348623157e+308,
     NAN = 0 / 0;
 /** Used as references for the maximum length and index of an array. */
 var MAX_ARRAY_LENGTH = 4294967295,
     MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
     HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
 /** Used to associate wrap methods with their bit flags. */
 var wrapFlags = [
   ['ary', WRAP_ARY_FLAG],
   ['bind', WRAP_BIND_FLAG],
   ['bindKey', WRAP_BIND_KEY_FLAG],
   ['curry', WRAP_CURRY_FLAG],
   ['curryRight', WRAP_CURRY_RIGHT_FLAG],
   ['flip', WRAP_FLIP_FLAG],
   ['partial', WRAP_PARTIAL_FLAG],
   ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
   ['rearg', WRAP_REARG_FLAG]
 ];
 /** `Object#toString` result references. */
 var argsTag = '[object Arguments]',
     arrayTag = '[object Array]',
     asyncTag = '[object AsyncFunction]',
     boolTag = '[object Boolean]',
     dateTag = '[object Date]',
     domExcTag = '[object DOMException]',
     errorTag = '[object Error]',
     funcTag = '[object Function]',
     genTag = '[object GeneratorFunction]',
     mapTag = '[object Map]',
     numberTag = '[object Number]',
     nullTag = '[object Null]',
     objectTag = '[object Object]',
     promiseTag = '[object Promise]',
     proxyTag = '[object Proxy]',
     regexpTag = '[object RegExp]',
     setTag = '[object Set]',
     stringTag = '[object String]',
     symbolTag = '[object Symbol]',
     undefinedTag = '[object Undefined]',
     weakMapTag = '[object WeakMap]',
     weakSetTag = '[object WeakSet]';
 var arrayBufferTag = '[object ArrayBuffer]',
     dataViewTag = '[object DataView]',
     float32Tag = '[object Float32Array]',
     float64Tag = '[object Float64Array]',
     int8Tag = '[object Int8Array]',
     int16Tag = '[object Int16Array]',
     int32Tag = '[object Int32Array]',
     uint8Tag = '[object Uint8Array]',
     uint8ClampedTag = '[object Uint8ClampedArray]',
     uint16Tag = '[object Uint16Array]',
     uint32Tag = '[object Uint32Array]';
 /** Used to match empty string literals in compiled template source. */
 var reEmptyStringLeading = /\b__p \+= ;/g,
     reEmptyStringMiddle = /\b(__p \+=)  \+/g,
     reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n;/g;
 /** Used to match HTML entities and HTML characters. */
 var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
     reUnescapedHtml = /[&<>"']/g,
     reHasEscapedHtml = RegExp(reEscapedHtml.source),
     reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
 /** Used to match template delimiters. */
 var reEscape = /<%-([\s\S]+?)%>/g,
     reEvaluate = /<%([\s\S]+?)%>/g,
     reInterpolate = /<%=([\s\S]+?)%>/g;
 /** Used to match property names within property paths. */
 var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
     reIsPlainProp = /^\w*$/,
     rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
 /**
  * Used to match `RegExp`
  * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
  */
 var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
     reHasRegExpChar = RegExp(reRegExpChar.source);
 /** Used to match leading and trailing whitespace. */
 var reTrim = /^\s+|\s+$/g,
     reTrimStart = /^\s+/,
     reTrimEnd = /\s+$/;
 /** Used to match wrap detail comments. */
 var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
     reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
     reSplitDetails = /,? & /;
 /** Used to match words composed of alphanumeric characters. */
 var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
 /** Used to match backslashes in property paths. */
 var reEscapeChar = /\\(\\)?/g;
 /**
  * Used to match
  * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
  */
 var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
 /** Used to match `RegExp` flags from their coerced string values. */
 var reFlags = /\w*$/;
 /** Used to detect bad signed hexadecimal string values. */
 var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
 /** Used to detect binary string values. */
 var reIsBinary = /^0b[01]+$/i;
 /** Used to detect host constructors (Safari). */
 var reIsHostCtor = /^\[object .+?Constructor\]$/;
 /** Used to detect octal string values. */
 var reIsOctal = /^0o[0-7]+$/i;
 /** Used to detect unsigned integer values. */
 var reIsUint = /^(?:0|[1-9]\d*)$/;
 /** Used to match Latin Unicode letters (excluding mathematical operators). */
 var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
 /** Used to ensure capturing order of template delimiters. */
 var reNoMatch = /($^)/;
 /** Used to match unescaped characters in compiled string literals. */
 var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
 /** Used to compose unicode character classes. */
 var rsAstralRange = '\\ud800-\\udfff',
     rsComboMarksRange = '\\u0300-\\u036f',
     reComboHalfMarksRange = '\\ufe20-\\ufe2f',
     rsComboSymbolsRange = '\\u20d0-\\u20ff',
     rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
     rsDingbatRange = '\\u2700-\\u27bf',
     rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
     rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
     rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
     rsPunctuationRange = '\\u2000-\\u206f',
     rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
     rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
     rsVarRange = '\\ufe0e\\ufe0f',
     rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
 /** Used to compose unicode capture groups. */
 var rsApos = "['\u2019]",
     rsAstral = '[' + rsAstralRange + ']',
     rsBreak = '[' + rsBreakRange + ']',
     rsCombo = '[' + rsComboRange + ']',
     rsDigits = '\\d+',
     rsDingbat = '[' + rsDingbatRange + ']',
     rsLower = '[' + rsLowerRange + ']',
     rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
     rsFitz = '\\ud83c[\\udffb-\\udfff]',
     rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
     rsNonAstral = '[^' + rsAstralRange + ']',
     rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
     rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
     rsUpper = '[' + rsUpperRange + ']',
     rsZWJ = '\\u200d';
 /** Used to compose unicode regexes. */
 var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
     rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
     rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
     rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
     reOptMod = rsModifier + '?',
     rsOptVar = '[' + rsVarRange + ']?',
     rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
     rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])',
     rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])',
     rsSeq = rsOptVar + reOptMod + rsOptJoin,
     rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
     rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
 /** Used to match apostrophes. */
 var reApos = RegExp(rsApos, 'g');
 /**
  * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
  * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
  */
 var reComboMark = RegExp(rsCombo, 'g');
 /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
 var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
 /** Used to match complex or compound words. */
 var reUnicodeWord = RegExp([
   rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
   rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
   rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
   rsUpper + '+' + rsOptContrUpper,
   rsOrdUpper,
   rsOrdLower,
   rsDigits,
   rsEmoji
 ].join('|'), 'g');
 /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
 var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange  + rsComboRange + rsVarRange + ']');
 /** Used to detect strings that need a more robust regexp to match words. */
 var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
 /** Used to assign default `context` object properties. */
 var contextProps = [
   'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',
   'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
   'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
   'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
   '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
 ];
 /** Used to make template sourceURLs easier to identify. */
 var templateCounter = -1;
 /** Used to identify `toStringTag` values of typed arrays. */
 var typedArrayTags = {};
 typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
 typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
 typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
 typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
 typedArrayTags[uint32Tag] = true;
 typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
 typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
 typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
 typedArrayTags[errorTag] = typedArrayTags[funcTag] =
 typedArrayTags[mapTag] = typedArrayTags[numberTag] =
 typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
 typedArrayTags[setTag] = typedArrayTags[stringTag] =
 typedArrayTags[weakMapTag] = false;
 /** Used to identify `toStringTag` values supported by `_.clone`. */
 var cloneableTags = {};
 cloneableTags[argsTag] = cloneableTags[arrayTag] =
 cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
 cloneableTags[boolTag] = cloneableTags[dateTag] =
 cloneableTags[float32Tag] = cloneableTags[float64Tag] =
 cloneableTags[int8Tag] = cloneableTags[int16Tag] =
 cloneableTags[int32Tag] = cloneableTags[mapTag] =
 cloneableTags[numberTag] = cloneableTags[objectTag] =
 cloneableTags[regexpTag] = cloneableTags[setTag] =
 cloneableTags[stringTag] = cloneableTags[symbolTag] =
 cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
 cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
 cloneableTags[errorTag] = cloneableTags[funcTag] =
 cloneableTags[weakMapTag] = false;
 /** Used to map Latin Unicode letters to basic Latin letters. */
 var deburredLetters = {
   // Latin-1 Supplement block.
   '\xc0': 'A',  '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
   '\xe0': 'a',  '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
   '\xc7': 'C',  '\xe7': 'c',
   '\xd0': 'D',  '\xf0': 'd',
   '\xc8': 'E',  '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
   '\xe8': 'e',  '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
   '\xcc': 'I',  '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
   '\xec': 'i',  '\xed': 'i', '\xee': 'i', '\xef': 'i',
   '\xd1': 'N',  '\xf1': 'n',
   '\xd2': 'O',  '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
   '\xf2': 'o',  '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
   '\xd9': 'U',  '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
   '\xf9': 'u',  '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
   '\xdd': 'Y',  '\xfd': 'y', '\xff': 'y',
   '\xc6': 'Ae', '\xe6': 'ae',
   '\xde': 'Th', '\xfe': 'th',
   '\xdf': 'ss',
   // Latin Extended-A block.
   '\u0100': 'A',  '\u0102': 'A', '\u0104': 'A',
   '\u0101': 'a',  '\u0103': 'a', '\u0105': 'a',
   '\u0106': 'C',  '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
   '\u0107': 'c',  '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
   '\u010e': 'D',  '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
   '\u0112': 'E',  '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
   '\u0113': 'e',  '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
   '\u011c': 'G',  '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
   '\u011d': 'g',  '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
   '\u0124': 'H',  '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
   '\u0128': 'I',  '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
   '\u0129': 'i',  '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
   '\u0134': 'J',  '\u0135': 'j',
   '\u0136': 'K',  '\u0137': 'k', '\u0138': 'k',
   '\u0139': 'L',  '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
   '\u013a': 'l',  '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
   '\u0143': 'N',  '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
   '\u0144': 'n',  '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
   '\u014c': 'O',  '\u014e': 'O', '\u0150': 'O',
   '\u014d': 'o',  '\u014f': 'o', '\u0151': 'o',
   '\u0154': 'R',  '\u0156': 'R', '\u0158': 'R',
   '\u0155': 'r',  '\u0157': 'r', '\u0159': 'r',
   '\u015a': 'S',  '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
   '\u015b': 's',  '\u015d': 's', '\u015f': 's', '\u0161': 's',
   '\u0162': 'T',  '\u0164': 'T', '\u0166': 'T',
   '\u0163': 't',  '\u0165': 't', '\u0167': 't',
   '\u0168': 'U',  '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
   '\u0169': 'u',  '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
   '\u0174': 'W',  '\u0175': 'w',
   '\u0176': 'Y',  '\u0177': 'y', '\u0178': 'Y',
   '\u0179': 'Z',  '\u017b': 'Z', '\u017d': 'Z',
   '\u017a': 'z',  '\u017c': 'z', '\u017e': 'z',
   '\u0132': 'IJ', '\u0133': 'ij',
   '\u0152': 'Oe', '\u0153': 'oe',
   '\u0149': "'n", '\u017f': 's'
 };
 /** Used to map characters to HTML entities. */
 var htmlEscapes = {
   '&': '&',
   '<': '<',
   '>': '>',
   '"': '"',
   "'": '''
 };
 /** Used to map HTML entities to characters. */
 var htmlUnescapes = {
   '&': '&',
   '<': '<',
   '>': '>',
   '"': '"',
   ''': "'"
 };
 /** Used to escape characters for inclusion in compiled string literals. */
 var stringEscapes = {
   '\\': '\\',
   "'": "'",
   '\n': 'n',
   '\r': 'r',
   '\u2028': 'u2028',
   '\u2029': 'u2029'
 };
 /** Built-in method references without a dependency on `root`. */
 var freeParseFloat = parseFloat,
     freeParseInt = parseInt;
 /** Detect free variable `global` from Node.js. */
 var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
 /** Detect free variable `self`. */
 var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
 /** Used as a reference to the global object. */
 var root = freeGlobal || freeSelf || Function('return this')();
 /** Detect free variable `exports`. */
 var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
 /** Detect free variable `module`. */
 var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
 /** Detect the popular CommonJS extension `module.exports`. */
 var moduleExports = freeModule && freeModule.exports === freeExports;
 /** Detect free variable `process` from Node.js. */
 var freeProcess = moduleExports && freeGlobal.process;
 /** Used to access faster Node.js helpers. */
 var nodeUtil = (function() {
   try {
     // Use `util.types` for Node.js 10+.
     var types = freeModule && freeModule.require && freeModule.require('util').types;
     if (types) {
       return types;
     }
     // Legacy `process.binding('util')` for Node.js < 10.
     return freeProcess && freeProcess.binding && freeProcess.binding('util');
   } catch (e) {}
 }());
 /* Node.js helper references. */
 var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
     nodeIsDate = nodeUtil && nodeUtil.isDate,
     nodeIsMap = nodeUtil && nodeUtil.isMap,
     nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
     nodeIsSet = nodeUtil && nodeUtil.isSet,
     nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
 /*--------------------------------------------------------------------------*/
 /**
  * A faster alternative to `Function#apply`, this function invokes `func`
  * with the `this` binding of `thisArg` and the arguments of `args`.
  *
  * @private
  * @param {Function} func The function to invoke.
  * @param {*} thisArg The `this` binding of `func`.
  * @param {Array} args The arguments to invoke `func` with.
  * @returns {*} Returns the result of `func`.
  */
 function apply(func, thisArg, args) {
   switch (args.length) {
     case 0: return func.call(thisArg);
     case 1: return func.call(thisArg, args[0]);
     case 2: return func.call(thisArg, args[0], args[1]);
     case 3: return func.call(thisArg, args[0], args[1], args[2]);
   }
   return func.apply(thisArg, args);
 }
 /**
  * A specialized version of `baseAggregator` for arrays.
  *
  * @private
  * @param {Array} [array] The array to iterate over.
  * @param {Function} setter The function to set `accumulator` values.
  * @param {Function} iteratee The iteratee to transform keys.
  * @param {Object} accumulator The initial aggregated object.
  * @returns {Function} Returns `accumulator`.
  */
 function arrayAggregator(array, setter, iteratee, accumulator) {
   var index = -1,
       length = array == null ? 0 : array.length;
   while (++index < length) {
     var value = array[index];
     setter(accumulator, value, iteratee(value), array);
   }
   return accumulator;
 }
 /**
  * A specialized version of `_.forEach` for arrays without support for
  * iteratee shorthands.
  *
  * @private
  * @param {Array} [array] The array to iterate over.
  * @param {Function} iteratee The function invoked per iteration.
  * @returns {Array} Returns `array`.
  */
 function arrayEach(array, iteratee) {
   var index = -1,
       length = array == null ? 0 : array.length;
   while (++index < length) {
     if (iteratee(array[index], index, array) === false) {
       break;
     }
   }
   return array;
 }
 /**
  * A specialized version of `_.forEachRight` for arrays without support for
  * iteratee shorthands.
  *
  * @private
  * @param {Array} [array] The array to iterate over.
  * @param {Function} iteratee The function invoked per iteration.
  * @returns {Array} Returns `array`.
  */
 function arrayEachRight(array, iteratee) {
   var length = array == null ? 0 : array.length;
   while (length--) {
     if (iteratee(array[length], length, array) === false) {
       break;
     }
   }
   return array;
 }
 /**
  * A specialized version of `_.every` for arrays without support for
  * iteratee shorthands.
  *
  * @private
  * @param {Array} [array] The array to iterate over.
  * @param {Function} predicate The function invoked per iteration.
  * @returns {boolean} Returns `true` if all elements pass the predicate check,
  *  else `false`.
  */
 function arrayEvery(array, predicate) {
   var index = -1,
       length = array == null ? 0 : array.length;
   while (++index < length) {
     if (!predicate(array[index], index, array)) {
       return false;
     }
   }
   return true;
 }
 /**
  * A specialized version of `_.filter` for arrays without support for
  * iteratee shorthands.
  *
  * @private
  * @param {Array} [array] The array to iterate over.
  * @param {Function} predicate The function invoked per iteration.
  * @returns {Array} Returns the new filtered array.
  */
 function arrayFilter(array, predicate) {
   var index = -1,
       length = array == null ? 0 : array.length,
       resIndex = 0,
       result = [];
   while (++index < length) {
     var value = array[index];
     if (predicate(value, index, array)) {
       result[resIndex++] = value;
     }
   }
   return result;
 }
 /**
  * A specialized version of `_.includes` for arrays without support for
  * specifying an index to search from.
  *
  * @private
  * @param {Array} [array] The array to inspect.
  * @param {*} target The value to search for.
  * @returns {boolean} Returns `true` if `target` is found, else `false`.
  */
 function arrayIncludes(array, value) {
   var length = array == null ? 0 : array.length;
   return !!length && baseIndexOf(array, value, 0) > -1;
 }
 /**
  * This function is like `arrayIncludes` except that it accepts a comparator.
  *
  * @private
  * @param {Array} [array] The array to inspect.
  * @param {*} target The value to search for.
  * @param {Function} comparator The comparator invoked per element.
  * @returns {boolean} Returns `true` if `target` is found, else `false`.
  */
 function arrayIncludesWith(array, value, comparator) {
   var index = -1,
       length = array == null ? 0 : array.length;
   while (++index < length) {
     if (comparator(value, array[index])) {
       return true;
     }
   }
   return false;
 }
 /**
  * A specialized version of `_.map` for arrays without support for iteratee
  * shorthands.
  *
  * @private
  * @param {Array} [array] The array to iterate over.
  * @param {Function} iteratee The function invoked per iteration.
  * @returns {Array} Returns the new mapped array.
  */
 function arrayMap(array, iteratee) {
   var index = -1,
       length = array == null ? 0 : array.length,
       result = Array(length);
   while (++index < length) {
     result[index] = iteratee(array[index], index, array);
   }
   return result;
 }
 /**
  * Appends the elements of `values` to `array`.
  *
  * @private
  * @param {Array} array The array to modify.
  * @param {Array} values The values to append.
  * @returns {Array} Returns `array`.
  */
 function arrayPush(array, values) {
   var index = -1,
       length = values.length,
       offset = array.length;
   while (++index < length) {
     array[offset + index] = values[index];
   }
   return array;
 }
 /**
  * A specialized version of `_.reduce` for arrays without support for
  * iteratee shorthands.
  *
  * @private
  * @param {Array} [array] The array to iterate over.
  * @param {Function} iteratee The function invoked per iteration.
  * @param {*} [accumulator] The initial value.
  * @param {boolean} [initAccum] Specify using the first element of `array` as
  *  the initial value.
  * @returns {*} Returns the accumulated value.
  */
 function arrayReduce(array, iteratee, accumulator, initAccum) {
   var index = -1,
       length = array == null ? 0 : array.length;
   if (initAccum && length) {
     accumulator = array[++index];
   }
   while (++index < length) {
     accumulator = iteratee(accumulator, array[index], index, array);
   }
   return accumulator;
 }
 /**
  * A specialized version of `_.reduceRight` for arrays without support for
  * iteratee shorthands.
  *
  * @private
  * @param {Array} [array] The array to iterate over.
  * @param {Function} iteratee The function invoked per iteration.
  * @param {*} [accumulator] The initial value.
  * @param {boolean} [initAccum] Specify using the last element of `array` as
  *  the initial value.
  * @returns {*} Returns the accumulated value.
  */
 function arrayReduceRight(array, iteratee, accumulator, initAccum) {
   var length = array == null ? 0 : array.length;
   if (initAccum && length) {
     accumulator = array[--length];
   }
   while (length--) {
     accumulator = iteratee(accumulator, array[length], length, array);
   }
   return accumulator;
 }
 /**
  * A specialized version of `_.some` for arrays without support for iteratee
  * shorthands.
  *
  * @private
  * @param {Array} [array] The array to iterate over.
  * @param {Function} predicate The function invoked per iteration.
  * @returns {boolean} Returns `true` if any element passes the predicate check,
  *  else `false`.
  */
 function arraySome(array, predicate) {
   var index = -1,
       length = array == null ? 0 : array.length;
   while (++index < length) {
     if (predicate(array[index], index, array)) {
       return true;
     }
   }
   return false;
 }
 /**
  * Gets the size of an ASCII `string`.
  *
  * @private
  * @param {string} string The string inspect.
  * @returns {number} Returns the string size.
  */
 var asciiSize = baseProperty('length');
 /**
  * Converts an ASCII `string` to an array.
  *
  * @private
  * @param {string} string The string to convert.
  * @returns {Array} Returns the converted array.
  */
 function asciiToArray(string) {
   return string.split();
 }
 /**
  * Splits an ASCII `string` into an array of its words.
  *
  * @private
  * @param {string} The string to inspect.
  * @returns {Array} Returns the words of `string`.
  */
 function asciiWords(string) {
   return string.match(reAsciiWord) || [];
 }
 /**
  * The base implementation of methods like `_.findKey` and `_.findLastKey`,
  * without support for iteratee shorthands, which iterates over `collection`
  * using `eachFunc`.
  *
  * @private
  * @param {Array|Object} collection The collection to inspect.
  * @param {Function} predicate The function invoked per iteration.
  * @param {Function} eachFunc The function to iterate over `collection`.
  * @returns {*} Returns the found element or its key, else `undefined`.
  */
 function baseFindKey(collection, predicate, eachFunc) {
   var result;
   eachFunc(collection, function(value, key, collection) {
     if (predicate(value, key, collection)) {
       result = key;
       return false;
     }
   });
   return result;
 }
 /**
  * The base implementation of `_.findIndex` and `_.findLastIndex` without
  * support for iteratee shorthands.
  *
  * @private
  * @param {Array} array The array to inspect.
  * @param {Function} predicate The function invoked per iteration.
  * @param {number} fromIndex The index to search from.
  * @param {boolean} [fromRight] Specify iterating from right to left.
  * @returns {number} Returns the index of the matched value, else `-1`.
  */
 function baseFindIndex(array, predicate, fromIndex, fromRight) {
   var length = array.length,
       index = fromIndex + (fromRight ? 1 : -1);
   while ((fromRight ? index-- : ++index < length)) {
     if (predicate(array[index], index, array)) {
       return index;
     }
   }
   return -1;
 }
 /**
  * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
  *
  * @private
  * @param {Array} array The array to inspect.
  * @param {*} value The value to search for.
  * @param {number} fromIndex The index to search from.
  * @returns {number} Returns the index of the matched value, else `-1`.
  */
 function baseIndexOf(array, value, fromIndex) {
   return value === value
     ? strictIndexOf(array, value, fromIndex)
     : baseFindIndex(array, baseIsNaN, fromIndex);
 }
 /**
  * This function is like `baseIndexOf` except that it accepts a comparator.
  *
  * @private
  * @param {Array} array The array to inspect.
  * @param {*} value The value to search for.
  * @param {number} fromIndex The index to search from.
  * @param {Function} comparator The comparator invoked per element.
  * @returns {number} Returns the index of the matched value, else `-1`.
  */
 function baseIndexOfWith(array, value, fromIndex, comparator) {
   var index = fromIndex - 1,
       length = array.length;
   while (++index < length) {
     if (comparator(array[index], value)) {
       return index;
     }
   }
   return -1;
 }
 /**
  * The base implementation of `_.isNaN` without support for number objects.
  *
  * @private
  * @param {*} value The value to check.
  * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
  */
 function baseIsNaN(value) {
   return value !== value;
 }
 /**
  * The base implementation of `_.mean` and `_.meanBy` without support for
  * iteratee shorthands.
  *
  * @private
  * @param {Array} array The array to iterate over.
  * @param {Function} iteratee The function invoked per iteration.
  * @returns {number} Returns the mean.
  */
 function baseMean(array, iteratee) {
   var length = array == null ? 0 : array.length;
   return length ? (baseSum(array, iteratee) / length) : NAN;
 }
 /**
  * The base implementation of `_.property` without support for deep paths.
  *
  * @private
  * @param {string} key The key of the property to get.
  * @returns {Function} Returns the new accessor function.
  */
 function baseProperty(key) {
   return function(object) {
     return object == null ? undefined : object[key];
   };
 }
 /**
  * The base implementation of `_.propertyOf` without support for deep paths.
  *
  * @private
  * @param {Object} object The object to query.
  * @returns {Function} Returns the new accessor function.
  */
 function basePropertyOf(object) {
   return function(key) {
     return object == null ? undefined : object[key];
   };
 }
 /**
  * The base implementation of `_.reduce` and `_.reduceRight`, without support
  * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
  *
  * @private
  * @param {Array|Object} collection The collection to iterate over.
  * @param {Function} iteratee The function invoked per iteration.
  * @param {*} accumulator The initial value.
  * @param {boolean} initAccum Specify using the first or last element of
  *  `collection` as the initial value.
  * @param {Function} eachFunc The function to iterate over `collection`.
  * @returns {*} Returns the accumulated value.
  */
 function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
   eachFunc(collection, function(value, index, collection) {
     accumulator = initAccum
       ? (initAccum = false, value)
       : iteratee(accumulator, value, index, collection);
   });
   return accumulator;
 }
 /**
  * The base implementation of `_.sortBy` which uses `comparer` to define the
  * sort order of `array` and replaces criteria objects with their corresponding
  * values.
  *
  * @private
  * @param {Array} array The array to sort.
  * @param {Function} comparer The function to define sort order.
  * @returns {Array} Returns `array`.
  */
 function baseSortBy(array, comparer) {
   var length = array.length;
   array.sort(comparer);
   while (length--) {
     array[length] = array[length].value;
   }
   return array;
 }
 /**
  * The base implementation of `_.sum` and `_.sumBy` without support for
  * iteratee shorthands.
  *
  * @private
  * @param {Array} array The array to iterate over.
  * @param {Function} iteratee The function invoked per iteration.
  * @returns {number} Returns the sum.
  */
 function baseSum(array, iteratee) {
   var result,
       index = -1,
       length = array.length;
   while (++index < length) {
     var current = iteratee(array[index]);
     if (current !== undefined) {
       result = result === undefined ? current : (result + current);
     }
   }
   return result;
 }
 /**
  * The base implementation of `_.times` without support for iteratee shorthands
  * or max array length checks.
  *
  * @private
  * @param {number} n The number of times to invoke `iteratee`.
  * @param {Function} iteratee The function invoked per iteration.
  * @returns {Array} Returns the array of results.
  */
 function baseTimes(n, iteratee) {
   var index = -1,
       result = Array(n);
   while (++index < n) {
     result[index] = iteratee(index);
   }
   return result;
 }
 /**
  * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
  * of key-value pairs for `object` corresponding to the property names of `props`.
  *
  * @private
  * @param {Object} object The object to query.
  * @param {Array} props The property names to get values for.
  * @returns {Object} Returns the key-value pairs.
  */
 function baseToPairs(object, props) {
   return arrayMap(props, function(key) {
     return [key, object[key]];
   });
 }
 /**
  * The base implementation of `_.unary` without support for storing metadata.
  *
  * @private
  * @param {Function} func The function to cap arguments for.
  * @returns {Function} Returns the new capped function.
  */
 function baseUnary(func) {
   return function(value) {
     return func(value);
   };
 }
 /**
  * The base implementation of `_.values` and `_.valuesIn` which creates an
  * array of `object` property values corresponding to the property names
  * of `props`.
  *
  * @private
  * @param {Object} object The object to query.
  * @param {Array} props The property names to get values for.
  * @returns {Object} Returns the array of property values.
  */
 function baseValues(object, props) {
   return arrayMap(props, function(key) {
     return object[key];
   });
 }
 /**
  * Checks if a `cache` value for `key` exists.
  *
  * @private
  * @param {Object} cache The cache to query.
  * @param {string} key The key of the entry to check.
  * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
  */
 function cacheHas(cache, key) {
   return cache.has(key);
 }
 /**
  * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
  * that is not found in the character symbols.
  *
  * @private
  * @param {Array} strSymbols The string symbols to inspect.
  * @param {Array} chrSymbols The character symbols to find.
  * @returns {number} Returns the index of the first unmatched string symbol.
  */
 function charsStartIndex(strSymbols, chrSymbols) {
   var index = -1,
       length = strSymbols.length;
   while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
   return index;
 }
 /**
  * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
  * that is not found in the character symbols.
  *
  * @private
  * @param {Array} strSymbols The string symbols to inspect.
  * @param {Array} chrSymbols The character symbols to find.
  * @returns {number} Returns the index of the last unmatched string symbol.
  */
 function charsEndIndex(strSymbols, chrSymbols) {
   var index = strSymbols.length;
   while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
   return index;
 }
 /**
  * Gets the number of `placeholder` occurrences in `array`.
  *
  * @private
  * @param {Array} array The array to inspect.
  * @param {*} placeholder The placeholder to search for.
  * @returns {number} Returns the placeholder count.
  */
 function countHolders(array, placeholder) {
   var length = array.length,
       result = 0;
   while (length--) {
     if (array[length] === placeholder) {
       ++result;
     }
   }
   return result;
 }
 /**
  * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
  * letters to basic Latin letters.
  *
  * @private
  * @param {string} letter The matched letter to deburr.
  * @returns {string} Returns the deburred letter.
  */
 var deburrLetter = basePropertyOf(deburredLetters);
 /**
  * Used by `_.escape` to convert characters to HTML entities.
  *
  * @private
  * @param {string} chr The matched character to escape.
  * @returns {string} Returns the escaped character.
  */
 var escapeHtmlChar = basePropertyOf(htmlEscapes);
 /**
  * Used by `_.template` to escape characters for inclusion in compiled string literals.
  *
  * @private
  * @param {string} chr The matched character to escape.
  * @returns {string} Returns the escaped character.
  */
 function escapeStringChar(chr) {
   return '\\' + stringEscapes[chr];
 }
 /**
  * Gets the value at `key` of `object`.
  *
  * @private
  * @param {Object} [object] The object to query.
  * @param {string} key The key of the property to get.
  * @returns {*} Returns the property value.
  */
 function getValue(object, key) {
   return object == null ? undefined : object[key];
 }
 /**
  * Checks if `string` contains Unicode symbols.
  *
  * @private
  * @param {string} string The string to inspect.
  * @returns {boolean} Returns `true` if a symbol is found, else `false`.
  */
 function hasUnicode(string) {
   return reHasUnicode.test(string);
 }
 /**
  * Checks if `string` contains a word composed of Unicode symbols.
  *
  * @private
  * @param {string} string The string to inspect.
  * @returns {boolean} Returns `true` if a word is found, else `false`.
  */
 function hasUnicodeWord(string) {
   return reHasUnicodeWord.test(string);
 }
 /**
  * Converts `iterator` to an array.
  *
  * @private
  * @param {Object} iterator The iterator to convert.
  * @returns {Array} Returns the converted array.
  */
 function iteratorToArray(iterator) {
   var data,
       result = [];
   while (!(data = iterator.next()).done) {
     result.push(data.value);
   }
   return result;
 }
 /**
  * Converts `map` to its key-value pairs.
  *
  * @private
  * @param {Object} map The map to convert.
  * @returns {Array} Returns the key-value pairs.
  */
 function mapToArray(map) {
   var index = -1,
       result = Array(map.size);
   map.forEach(function(value, key) {
     result[++index] = [key, value];
   });
   return result;
 }
 /**
  * Creates a unary function that invokes `func` with its argument transformed.
  *
  * @private
  * @param {Function} func The function to wrap.
  * @param {Function} transform The argument transform.
  * @returns {Function} Returns the new function.
  */
 function overArg(func, transform) {
   return function(arg) {
     return func(transform(arg));
   };
 }
 /**
  * Replaces all `placeholder` elements in `array` with an internal placeholder
  * and returns an array of their indexes.
  *
  * @private
  * @param {Array} array The array to modify.
  * @param {*} placeholder The placeholder to replace.
  * @returns {Array} Returns the new array of placeholder indexes.
  */
 function replaceHolders(array, placeholder) {
   var index = -1,
       length = array.length,
       resIndex = 0,
       result = [];
   while (++index < length) {
     var value = array[index];
     if (value === placeholder || value === PLACEHOLDER) {
       array[index] = PLACEHOLDER;
       result[resIndex++] = index;
     }
   }
   return result;
 }
 /**
  * Converts `set` to an array of its values.
  *
  * @private
  * @param {Object} set The set to convert.
  * @returns {Array} Returns the values.
  */
 function setToArray(set) {
   var index = -1,
       result = Array(set.size);
   set.forEach(function(value) {
     result[++index] = value;
   });
   return result;
 }
 /**
  * Converts `set` to its value-value pairs.
  *
  * @private
  * @param {Object} set The set to convert.
  * @returns {Array} Returns the value-value pairs.
  */
 function setToPairs(set) {
   var index = -1,
       result = Array(set.size);
   set.forEach(function(value) {
     result[++index] = [value, value];
   });
   return result;
 }
 /**
  * A specialized version of `_.indexOf` which performs strict equality
  * comparisons of values, i.e. `===`.
  *
  * @private
  * @param {Array} array The array to inspect.
  * @param {*} value The value to search for.
  * @param {number} fromIndex The index to search from.
  * @returns {number} Returns the index of the matched value, else `-1`.
  */
 function strictIndexOf(array, value, fromIndex) {
   var index = fromIndex - 1,
       length = array.length;
   while (++index < length) {
     if (array[index] === value) {
       return index;
     }
   }
   return -1;
 }
 /**
  * A specialized version of `_.lastIndexOf` which performs strict equality
  * comparisons of values, i.e. `===`.
  *
  * @private
  * @param {Array} array The array to inspect.
  * @param {*} value The value to search for.
  * @param {number} fromIndex The index to search from.
  * @returns {number} Returns the index of the matched value, else `-1`.
  */
 function strictLastIndexOf(array, value, fromIndex) {
   var index = fromIndex + 1;
   while (index--) {
     if (array[index] === value) {
       return index;
     }
   }
   return index;
 }
 /**
  * Gets the number of symbols in `string`.
  *
  * @private
  * @param {string} string The string to inspect.
  * @returns {number} Returns the string size.
  */
 function stringSize(string) {
   return hasUnicode(string)
     ? unicodeSize(string)
     : asciiSize(string);
 }
 /**
  * Converts `string` to an array.
  *
  * @private
  * @param {string} string The string to convert.
  * @returns {Array} Returns the converted array.
  */
 function stringToArray(string) {
   return hasUnicode(string)
     ? unicodeToArray(string)
     : asciiToArray(string);
 }
 /**
  * Used by `_.unescape` to convert HTML entities to characters.
  *
  * @private
  * @param {string} chr The matched character to unescape.
  * @returns {string} Returns the unescaped character.
  */
 var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
 /**
  * Gets the size of a Unicode `string`.
  *
  * @private
  * @param {string} string The string inspect.
  * @returns {number} Returns the string size.
  */
 function unicodeSize(string) {
   var result = reUnicode.lastIndex = 0;
   while (reUnicode.test(string)) {
     ++result;
   }
   return result;
 }
 /**
  * Converts a Unicode `string` to an array.
  *
  * @private
  * @param {string} string The string to convert.
  * @returns {Array} Returns the converted array.
  */
 function unicodeToArray(string) {
   return string.match(reUnicode) || [];
 }
 /**
  * Splits a Unicode `string` into an array of its words.
  *
  * @private
  * @param {string} The string to inspect.
  * @returns {Array} Returns the words of `string`.
  */
 function unicodeWords(string) {
   return string.match(reUnicodeWord) || [];
 }
 /*--------------------------------------------------------------------------*/
 /**
  * Create a new pristine `lodash` function using the `context` object.
  *
  * @static
  * @memberOf _
  * @since 1.1.0
  * @category Util
  * @param {Object} [context=root] The context object.
  * @returns {Function} Returns a new `lodash` function.
  * @example
  *
  * _.mixin({ 'foo': _.constant('foo') });
  *
  * var lodash = _.runInContext();
  * lodash.mixin({ 'bar': lodash.constant('bar') });
  *
  * _.isFunction(_.foo);
  * // => true
  * _.isFunction(_.bar);
  * // => false
  *
  * lodash.isFunction(lodash.foo);
  * // => false
  * lodash.isFunction(lodash.bar);
  * // => true
  *
  * // Create a suped-up `defer` in Node.js.
  * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
  */
 var runInContext = (function runInContext(context) {
   context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
   /** Built-in constructor references. */
   var Array = context.Array,
       Date = context.Date,
       Error = context.Error,
       Function = context.Function,
       Math = context.Math,
       Object = context.Object,
       RegExp = context.RegExp,
       String = context.String,
       TypeError = context.TypeError;
   /** Used for built-in method references. */
   var arrayProto = Array.prototype,
       funcProto = Function.prototype,
       objectProto = Object.prototype;
   /** Used to detect overreaching core-js shims. */
   var coreJsData = context['__core-js_shared__'];
   /** Used to resolve the decompiled source of functions. */
   var funcToString = funcProto.toString;
   /** Used to check objects for own properties. */
   var hasOwnProperty = objectProto.hasOwnProperty;
   /** Used to generate unique IDs. */
   var idCounter = 0;
   /** Used to detect methods masquerading as native. */
   var maskSrcKey = (function() {
     var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || );
     return uid ? ('Symbol(src)_1.' + uid) : ;
   }());
   /**
    * Used to resolve the
    * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
    * of values.
    */
   var nativeObjectToString = objectProto.toString;
   /** Used to infer the `Object` constructor. */
   var objectCtorString = funcToString.call(Object);
   /** Used to restore the original `_` reference in `_.noConflict`. */
   var oldDash = root._;
   /** Used to detect if a method is native. */
   var reIsNative = RegExp('^' +
     funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
     .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
   );
   /** Built-in value references. */
   var Buffer = moduleExports ? context.Buffer : undefined,
       Symbol = context.Symbol,
       Uint8Array = context.Uint8Array,
       allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,
       getPrototype = overArg(Object.getPrototypeOf, Object),
       objectCreate = Object.create,
       propertyIsEnumerable = objectProto.propertyIsEnumerable,
       splice = arrayProto.splice,
       spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,
       symIterator = Symbol ? Symbol.iterator : undefined,
       symToStringTag = Symbol ? Symbol.toStringTag : undefined;
   var defineProperty = (function() {
     try {
       var func = getNative(Object, 'defineProperty');
       func({}, , {});
       return func;
     } catch (e) {}
   }());
   /** Mocked built-ins. */
   var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
       ctxNow = Date && Date.now !== root.Date.now && Date.now,
       ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
   /* Built-in method references for those with the same name as other `lodash` methods. */
   var nativeCeil = Math.ceil,
       nativeFloor = Math.floor,
       nativeGetSymbols = Object.getOwnPropertySymbols,
       nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
       nativeIsFinite = context.isFinite,
       nativeJoin = arrayProto.join,
       nativeKeys = overArg(Object.keys, Object),
       nativeMax = Math.max,
       nativeMin = Math.min,
       nativeNow = Date.now,
       nativeParseInt = context.parseInt,
       nativeRandom = Math.random,
       nativeReverse = arrayProto.reverse;
   /* Built-in method references that are verified to be native. */
   var DataView = getNative(context, 'DataView'),
       Map = getNative(context, 'Map'),
       Promise = getNative(context, 'Promise'),
       Set = getNative(context, 'Set'),
       WeakMap = getNative(context, 'WeakMap'),
       nativeCreate = getNative(Object, 'create');
   /** Used to store function metadata. */
   var metaMap = WeakMap && new WeakMap;
   /** Used to lookup unminified function names. */
   var realNames = {};
   /** Used to detect maps, sets, and weakmaps. */
   var dataViewCtorString = toSource(DataView),
       mapCtorString = toSource(Map),
       promiseCtorString = toSource(Promise),
       setCtorString = toSource(Set),
       weakMapCtorString = toSource(WeakMap);
   /** Used to convert symbols to primitives and strings. */
   var symbolProto = Symbol ? Symbol.prototype : undefined,
       symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
       symbolToString = symbolProto ? symbolProto.toString : undefined;
   /*------------------------------------------------------------------------*/
   /**
    * Creates a `lodash` object which wraps `value` to enable implicit method
    * chain sequences. Methods that operate on and return arrays, collections,
    * and functions can be chained together. Methods that retrieve a single value
    * or may return a primitive value will automatically end the chain sequence
    * and return the unwrapped value. Otherwise, the value must be unwrapped
    * with `_#value`.
    *
    * Explicit chain sequences, which must be unwrapped with `_#value`, may be
    * enabled using `_.chain`.
    *
    * The execution of chained methods is lazy, that is, it's deferred until
    * `_#value` is implicitly or explicitly called.
    *
    * Lazy evaluation allows several methods to support shortcut fusion.
    * Shortcut fusion is an optimization to merge iteratee calls; this avoids
    * the creation of intermediate arrays and can greatly reduce the number of
    * iteratee executions. Sections of a chain sequence qualify for shortcut
    * fusion if the section is applied to an array and iteratees accept only
    * one argument. The heuristic for whether a section qualifies for shortcut
    * fusion is subject to change.
    *
    * Chaining is supported in custom builds as long as the `_#value` method is
    * directly or indirectly included in the build.
    *
    * In addition to lodash methods, wrappers have `Array` and `String` methods.
    *
    * The wrapper `Array` methods are:
    * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
    *
    * The wrapper `String` methods are:
    * `replace` and `split`
    *
    * The wrapper methods that support shortcut fusion are:
    * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
    * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
    * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
    *
    * The chainable wrapper methods are:
    * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
    * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
    * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
    * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
    * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
    * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
    * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
    * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
    * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
    * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
    * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
    * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
    * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
    * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
    * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
    * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
    * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
    * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
    * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
    * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
    * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
    * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
    * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
    * `zipObject`, `zipObjectDeep`, and `zipWith`
    *
    * The wrapper methods that are **not** chainable by default are:
    * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
    * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
    * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
    * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
    * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
    * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
    * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
    * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
    * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
    * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
    * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
    * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
    * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
    * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
    * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
    * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
    * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
    * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
    * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
    * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
    * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
    * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
    * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
    * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
    * `upperFirst`, `value`, and `words`
    *
    * @name _
    * @constructor
    * @category Seq
    * @param {*} value The value to wrap in a `lodash` instance.
    * @returns {Object} Returns the new `lodash` wrapper instance.
    * @example
    *
    * function square(n) {
    *   return n * n;
    * }
    *
    * var wrapped = _([1, 2, 3]);
    *
    * // Returns an unwrapped value.
    * wrapped.reduce(_.add);
    * // => 6
    *
    * // Returns a wrapped value.
    * var squares = wrapped.map(square);
    *
    * _.isArray(squares);
    * // => false
    *
    * _.isArray(squares.value());
    * // => true
    */
   function lodash(value) {
     if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
       if (value instanceof LodashWrapper) {
         return value;
       }
       if (hasOwnProperty.call(value, '__wrapped__')) {
         return wrapperClone(value);
       }
     }
     return new LodashWrapper(value);
   }
   /**
    * The base implementation of `_.create` without support for assigning
    * properties to the created object.
    *
    * @private
    * @param {Object} proto The object to inherit from.
    * @returns {Object} Returns the new object.
    */
   var baseCreate = (function() {
     function object() {}
     return function(proto) {
       if (!isObject(proto)) {
         return {};
       }
       if (objectCreate) {
         return objectCreate(proto);
       }
       object.prototype = proto;
       var result = new object;
       object.prototype = undefined;
       return result;
     };
   }());
   /**
    * The function whose prototype chain sequence wrappers inherit from.
    *
    * @private
    */
   function baseLodash() {
     // No operation performed.
   }
   /**
    * The base constructor for creating `lodash` wrapper objects.
    *
    * @private
    * @param {*} value The value to wrap.
    * @param {boolean} [chainAll] Enable explicit method chain sequences.
    */
   function LodashWrapper(value, chainAll) {
     this.__wrapped__ = value;
     this.__actions__ = [];
     this.__chain__ = !!chainAll;
     this.__index__ = 0;
     this.__values__ = undefined;
   }
   /**
    * By default, the template delimiters used by lodash are like those in
    * embedded Ruby (ERB) as well as ES2015 template strings. Change the
    * following template settings to use alternative delimiters.
    *
    * @static
    * @memberOf _
    * @type {Object}
    */
   lodash.templateSettings = {
     /**
      * Used to detect `data` property values to be HTML-escaped.
      *
      * @memberOf _.templateSettings
      * @type {RegExp}
      */
     'escape': reEscape,
     /**
      * Used to detect code to be evaluated.
      *
      * @memberOf _.templateSettings
      * @type {RegExp}
      */
     'evaluate': reEvaluate,
     /**
      * Used to detect `data` property values to inject.
      *
      * @memberOf _.templateSettings
      * @type {RegExp}
      */
     'interpolate': reInterpolate,
     /**
      * Used to reference the data object in the template text.
      *
      * @memberOf _.templateSettings
      * @type {string}
      */
     'variable': ,
     /**
      * Used to import variables into the compiled template.
      *
      * @memberOf _.templateSettings
      * @type {Object}
      */
     'imports': {
       /**
        * A reference to the `lodash` function.
        *
        * @memberOf _.templateSettings.imports
        * @type {Function}
        */
       '_': lodash
     }
   };
   // Ensure wrappers are instances of `baseLodash`.
   lodash.prototype = baseLodash.prototype;
   lodash.prototype.constructor = lodash;
   LodashWrapper.prototype = baseCreate(baseLodash.prototype);
   LodashWrapper.prototype.constructor = LodashWrapper;
   /*------------------------------------------------------------------------*/
   /**
    * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
    *
    * @private
    * @constructor
    * @param {*} value The value to wrap.
    */
   function LazyWrapper(value) {
     this.__wrapped__ = value;
     this.__actions__ = [];
     this.__dir__ = 1;
     this.__filtered__ = false;
     this.__iteratees__ = [];
     this.__takeCount__ = MAX_ARRAY_LENGTH;
     this.__views__ = [];
   }
   /**
    * Creates a clone of the lazy wrapper object.
    *
    * @private
    * @name clone
    * @memberOf LazyWrapper
    * @returns {Object} Returns the cloned `LazyWrapper` object.
    */
   function lazyClone() {
     var result = new LazyWrapper(this.__wrapped__);
     result.__actions__ = copyArray(this.__actions__);
     result.__dir__ = this.__dir__;
     result.__filtered__ = this.__filtered__;
     result.__iteratees__ = copyArray(this.__iteratees__);
     result.__takeCount__ = this.__takeCount__;
     result.__views__ = copyArray(this.__views__);
     return result;
   }
   /**
    * Reverses the direction of lazy iteration.
    *
    * @private
    * @name reverse
    * @memberOf LazyWrapper
    * @returns {Object} Returns the new reversed `LazyWrapper` object.
    */
   function lazyReverse() {
     if (this.__filtered__) {
       var result = new LazyWrapper(this);
       result.__dir__ = -1;
       result.__filtered__ = true;
     } else {
       result = this.clone();
       result.__dir__ *= -1;
     }
     return result;
   }
   /**
    * Extracts the unwrapped value from its lazy wrapper.
    *
    * @private
    * @name value
    * @memberOf LazyWrapper
    * @returns {*} Returns the unwrapped value.
    */
   function lazyValue() {
     var array = this.__wrapped__.value(),
         dir = this.__dir__,
         isArr = isArray(array),
         isRight = dir < 0,
         arrLength = isArr ? array.length : 0,
         view = getView(0, arrLength, this.__views__),
         start = view.start,
         end = view.end,
         length = end - start,
         index = isRight ? end : (start - 1),
         iteratees = this.__iteratees__,
         iterLength = iteratees.length,
         resIndex = 0,
         takeCount = nativeMin(length, this.__takeCount__);
     if (!isArr || (!isRight && arrLength == length && takeCount == length)) {
       return baseWrapperValue(array, this.__actions__);
     }
     var result = [];
     outer:
     while (length-- && resIndex < takeCount) {
       index += dir;
       var iterIndex = -1,
           value = array[index];
       while (++iterIndex < iterLength) {
         var data = iteratees[iterIndex],
             iteratee = data.iteratee,
             type = data.type,
             computed = iteratee(value);
         if (type == LAZY_MAP_FLAG) {
           value = computed;
         } else if (!computed) {
           if (type == LAZY_FILTER_FLAG) {
             continue outer;
           } else {
             break outer;
           }
         }
       }
       result[resIndex++] = value;
     }
     return result;
   }
   // Ensure `LazyWrapper` is an instance of `baseLodash`.
   LazyWrapper.prototype = baseCreate(baseLodash.prototype);
   LazyWrapper.prototype.constructor = LazyWrapper;
   /*------------------------------------------------------------------------*/
   /**
    * Creates a hash object.
    *
    * @private
    * @constructor
    * @param {Array} [entries] The key-value pairs to cache.
    */
   function Hash(entries) {
     var index = -1,
         length = entries == null ? 0 : entries.length;
     this.clear();
     while (++index < length) {
       var entry = entries[index];
       this.set(entry[0], entry[1]);
     }
   }
   /**
    * Removes all key-value entries from the hash.
    *
    * @private
    * @name clear
    * @memberOf Hash
    */
   function hashClear() {
     this.__data__ = nativeCreate ? nativeCreate(null) : {};
     this.size = 0;
   }
   /**
    * Removes `key` and its value from the hash.
    *
    * @private
    * @name delete
    * @memberOf Hash
    * @param {Object} hash The hash to modify.
    * @param {string} key The key of the value to remove.
    * @returns {boolean} Returns `true` if the entry was removed, else `false`.
    */
   function hashDelete(key) {
     var result = this.has(key) && delete this.__data__[key];
     this.size -= result ? 1 : 0;
     return result;
   }
   /**
    * Gets the hash value for `key`.
    *
    * @private
    * @name get
    * @memberOf Hash
    * @param {string} key The key of the value to get.
    * @returns {*} Returns the entry value.
    */
   function hashGet(key) {
     var data = this.__data__;
     if (nativeCreate) {
       var result = data[key];
       return result === HASH_UNDEFINED ? undefined : result;
     }
     return hasOwnProperty.call(data, key) ? data[key] : undefined;
   }
   /**
    * Checks if a hash value for `key` exists.
    *
    * @private
    * @name has
    * @memberOf Hash
    * @param {string} key The key of the entry to check.
    * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
    */
   function hashHas(key) {
     var data = this.__data__;
     return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
   }
   /**
    * Sets the hash `key` to `value`.
    *
    * @private
    * @name set
    * @memberOf Hash
    * @param {string} key The key of the value to set.
    * @param {*} value The value to set.
    * @returns {Object} Returns the hash instance.
    */
   function hashSet(key, value) {
     var data = this.__data__;
     this.size += this.has(key) ? 0 : 1;
     data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
     return this;
   }
   // Add methods to `Hash`.
   Hash.prototype.clear = hashClear;
   Hash.prototype['delete'] = hashDelete;
   Hash.prototype.get = hashGet;
   Hash.prototype.has = hashHas;
   Hash.prototype.set = hashSet;
   /*------------------------------------------------------------------------*/
   /**
    * Creates an list cache object.
    *
    * @private
    * @constructor
    * @param {Array} [entries] The key-value pairs to cache.
    */
   function ListCache(entries) {
     var index = -1,
         length = entries == null ? 0 : entries.length;
     this.clear();
     while (++index < length) {
       var entry = entries[index];
       this.set(entry[0], entry[1]);
     }
   }
   /**
    * Removes all key-value entries from the list cache.
    *
    * @private
    * @name clear
    * @memberOf ListCache
    */
   function listCacheClear() {
     this.__data__ = [];
     this.size = 0;
   }
   /**
    * Removes `key` and its value from the list cache.
    *
    * @private
    * @name delete
    * @memberOf ListCache
    * @param {string} key The key of the value to remove.
    * @returns {boolean} Returns `true` if the entry was removed, else `false`.
    */
   function listCacheDelete(key) {
     var data = this.__data__,
         index = assocIndexOf(data, key);
     if (index < 0) {
       return false;
     }
     var lastIndex = data.length - 1;
     if (index == lastIndex) {
       data.pop();
     } else {
       splice.call(data, index, 1);
     }
     --this.size;
     return true;
   }
   /**
    * Gets the list cache value for `key`.
    *
    * @private
    * @name get
    * @memberOf ListCache
    * @param {string} key The key of the value to get.
    * @returns {*} Returns the entry value.
    */
   function listCacheGet(key) {
     var data = this.__data__,
         index = assocIndexOf(data, key);
     return index < 0 ? undefined : data[index][1];
   }
   /**
    * Checks if a list cache value for `key` exists.
    *
    * @private
    * @name has
    * @memberOf ListCache
    * @param {string} key The key of the entry to check.
    * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
    */
   function listCacheHas(key) {
     return assocIndexOf(this.__data__, key) > -1;
   }
   /**
    * Sets the list cache `key` to `value`.
    *
    * @private
    * @name set
    * @memberOf ListCache
    * @param {string} key The key of the value to set.
    * @param {*} value The value to set.
    * @returns {Object} Returns the list cache instance.
    */
   function listCacheSet(key, value) {
     var data = this.__data__,
         index = assocIndexOf(data, key);
     if (index < 0) {
       ++this.size;
       data.push([key, value]);
     } else {
       data[index][1] = value;
     }
     return this;
   }
   // Add methods to `ListCache`.
   ListCache.prototype.clear = listCacheClear;
   ListCache.prototype['delete'] = listCacheDelete;
   ListCache.prototype.get = listCacheGet;
   ListCache.prototype.has = listCacheHas;
   ListCache.prototype.set = listCacheSet;
   /*------------------------------------------------------------------------*/
   /**
    * Creates a map cache object to store key-value pairs.
    *
    * @private
    * @constructor
    * @param {Array} [entries] The key-value pairs to cache.
    */
   function MapCache(entries) {
     var index = -1,
         length = entries == null ? 0 : entries.length;
     this.clear();
     while (++index < length) {
       var entry = entries[index];
       this.set(entry[0], entry[1]);
     }
   }
   /**
    * Removes all key-value entries from the map.
    *
    * @private
    * @name clear
    * @memberOf MapCache
    */
   function mapCacheClear() {
     this.size = 0;
     this.__data__ = {
       'hash': new Hash,
       'map': new (Map || ListCache),
       'string': new Hash
     };
   }
   /**
    * Removes `key` and its value from the map.
    *
    * @private
    * @name delete
    * @memberOf MapCache
    * @param {string} key The key of the value to remove.
    * @returns {boolean} Returns `true` if the entry was removed, else `false`.
    */
   function mapCacheDelete(key) {
     var result = getMapData(this, key)['delete'](key);
     this.size -= result ? 1 : 0;
     return result;
   }
   /**
    * Gets the map value for `key`.
    *
    * @private
    * @name get
    * @memberOf MapCache
    * @param {string} key The key of the value to get.
    * @returns {*} Returns the entry value.
    */
   function mapCacheGet(key) {
     return getMapData(this, key).get(key);
   }
   /**
    * Checks if a map value for `key` exists.
    *
    * @private
    * @name has
    * @memberOf MapCache
    * @param {string} key The key of the entry to check.
    * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
    */
   function mapCacheHas(key) {
     return getMapData(this, key).has(key);
   }
   /**
    * Sets the map `key` to `value`.
    *
    * @private
    * @name set
    * @memberOf MapCache
    * @param {string} key The key of the value to set.
    * @param {*} value The value to set.
    * @returns {Object} Returns the map cache instance.
    */
   function mapCacheSet(key, value) {
     var data = getMapData(this, key),
         size = data.size;
     data.set(key, value);
     this.size += data.size == size ? 0 : 1;
     return this;
   }
   // Add methods to `MapCache`.
   MapCache.prototype.clear = mapCacheClear;
   MapCache.prototype['delete'] = mapCacheDelete;
   MapCache.prototype.get = mapCacheGet;
   MapCache.prototype.has = mapCacheHas;
   MapCache.prototype.set = mapCacheSet;
   /*------------------------------------------------------------------------*/
   /**
    *
    * Creates an array cache object to store unique values.
    *
    * @private
    * @constructor
    * @param {Array} [values] The values to cache.
    */
   function SetCache(values) {
     var index = -1,
         length = values == null ? 0 : values.length;
     this.__data__ = new MapCache;
     while (++index < length) {
       this.add(values[index]);
     }
   }
   /**
    * Adds `value` to the array cache.
    *
    * @private
    * @name add
    * @memberOf SetCache
    * @alias push
    * @param {*} value The value to cache.
    * @returns {Object} Returns the cache instance.
    */
   function setCacheAdd(value) {
     this.__data__.set(value, HASH_UNDEFINED);
     return this;
   }
   /**
    * Checks if `value` is in the array cache.
    *
    * @private
    * @name has
    * @memberOf SetCache
    * @param {*} value The value to search for.
    * @returns {number} Returns `true` if `value` is found, else `false`.
    */
   function setCacheHas(value) {
     return this.__data__.has(value);
   }
   // Add methods to `SetCache`.
   SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
   SetCache.prototype.has = setCacheHas;
   /*------------------------------------------------------------------------*/
   /**
    * Creates a stack cache object to store key-value pairs.
    *
    * @private
    * @constructor
    * @param {Array} [entries] The key-value pairs to cache.
    */
   function Stack(entries) {
     var data = this.__data__ = new ListCache(entries);
     this.size = data.size;
   }
   /**
    * Removes all key-value entries from the stack.
    *
    * @private
    * @name clear
    * @memberOf Stack
    */
   function stackClear() {
     this.__data__ = new ListCache;
     this.size = 0;
   }
   /**
    * Removes `key` and its value from the stack.
    *
    * @private
    * @name delete
    * @memberOf Stack
    * @param {string} key The key of the value to remove.
    * @returns {boolean} Returns `true` if the entry was removed, else `false`.
    */
   function stackDelete(key) {
     var data = this.__data__,
         result = data['delete'](key);
     this.size = data.size;
     return result;
   }
   /**
    * Gets the stack value for `key`.
    *
    * @private
    * @name get
    * @memberOf Stack
    * @param {string} key The key of the value to get.
    * @returns {*} Returns the entry value.
    */
   function stackGet(key) {
     return this.__data__.get(key);
   }
   /**
    * Checks if a stack value for `key` exists.
    *
    * @private
    * @name has
    * @memberOf Stack
    * @param {string} key The key of the entry to check.
    * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
    */
   function stackHas(key) {
     return this.__data__.has(key);
   }
   /**
    * Sets the stack `key` to `value`.
    *
    * @private
    * @name set
    * @memberOf Stack
    * @param {string} key The key of the value to set.
    * @param {*} value The value to set.
    * @returns {Object} Returns the stack cache instance.
    */
   function stackSet(key, value) {
     var data = this.__data__;
     if (data instanceof ListCache) {
       var pairs = data.__data__;
       if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
         pairs.push([key, value]);
         this.size = ++data.size;
         return this;
       }
       data = this.__data__ = new MapCache(pairs);
     }
     data.set(key, value);
     this.size = data.size;
     return this;
   }
   // Add methods to `Stack`.
   Stack.prototype.clear = stackClear;
   Stack.prototype['delete'] = stackDelete;
   Stack.prototype.get = stackGet;
   Stack.prototype.has = stackHas;
   Stack.prototype.set = stackSet;
   /*------------------------------------------------------------------------*/
   /**
    * Creates an array of the enumerable property names of the array-like `value`.
    *
    * @private
    * @param {*} value The value to query.
    * @param {boolean} inherited Specify returning inherited property names.
    * @returns {Array} Returns the array of property names.
    */
   function arrayLikeKeys(value, inherited) {
     var isArr = isArray(value),
         isArg = !isArr && isArguments(value),
         isBuff = !isArr && !isArg && isBuffer(value),
         isType = !isArr && !isArg && !isBuff && isTypedArray(value),
         skipIndexes = isArr || isArg || isBuff || isType,
         result = skipIndexes ? baseTimes(value.length, String) : [],
         length = result.length;
     for (var key in value) {
       if ((inherited || hasOwnProperty.call(value, key)) &&
           !(skipIndexes && (
              // Safari 9 has enumerable `arguments.length` in strict mode.
              key == 'length' ||
              // Node.js 0.10 has enumerable non-index properties on buffers.
              (isBuff && (key == 'offset' || key == 'parent')) ||
              // PhantomJS 2 has enumerable non-index properties on typed arrays.
              (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
              // Skip index properties.
              isIndex(key, length)
           ))) {
         result.push(key);
       }
     }
     return result;
   }
   /**
    * A specialized version of `_.sample` for arrays.
    *
    * @private
    * @param {Array} array The array to sample.
    * @returns {*} Returns the random element.
    */
   function arraySample(array) {
     var length = array.length;
     return length ? array[baseRandom(0, length - 1)] : undefined;
   }
   /**
    * A specialized version of `_.sampleSize` for arrays.
    *
    * @private
    * @param {Array} array The array to sample.
    * @param {number} n The number of elements to sample.
    * @returns {Array} Returns the random elements.
    */
   function arraySampleSize(array, n) {
     return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
   }
   /**
    * A specialized version of `_.shuffle` for arrays.
    *
    * @private
    * @param {Array} array The array to shuffle.
    * @returns {Array} Returns the new shuffled array.
    */
   function arrayShuffle(array) {
     return shuffleSelf(copyArray(array));
   }
   /**
    * This function is like `assignValue` except that it doesn't assign
    * `undefined` values.
    *
    * @private
    * @param {Object} object The object to modify.
    * @param {string} key The key of the property to assign.
    * @param {*} value The value to assign.
    */
   function assignMergeValue(object, key, value) {
     if ((value !== undefined && !eq(object[key], value)) ||
         (value === undefined && !(key in object))) {
       baseAssignValue(object, key, value);
     }
   }
   /**
    * Assigns `value` to `key` of `object` if the existing value is not equivalent
    * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
    * for equality comparisons.
    *
    * @private
    * @param {Object} object The object to modify.
    * @param {string} key The key of the property to assign.
    * @param {*} value The value to assign.
    */
   function assignValue(object, key, value) {
     var objValue = object[key];
     if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
         (value === undefined && !(key in object))) {
       baseAssignValue(object, key, value);
     }
   }
   /**
    * Gets the index at which the `key` is found in `array` of key-value pairs.
    *
    * @private
    * @param {Array} array The array to inspect.
    * @param {*} key The key to search for.
    * @returns {number} Returns the index of the matched value, else `-1`.
    */
   function assocIndexOf(array, key) {
     var length = array.length;
     while (length--) {
       if (eq(array[length][0], key)) {
         return length;
       }
     }
     return -1;
   }
   /**
    * Aggregates elements of `collection` on `accumulator` with keys transformed
    * by `iteratee` and values set by `setter`.
    *
    * @private
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} setter The function to set `accumulator` values.
    * @param {Function} iteratee The iteratee to transform keys.
    * @param {Object} accumulator The initial aggregated object.
    * @returns {Function} Returns `accumulator`.
    */
   function baseAggregator(collection, setter, iteratee, accumulator) {
     baseEach(collection, function(value, key, collection) {
       setter(accumulator, value, iteratee(value), collection);
     });
     return accumulator;
   }
   /**
    * The base implementation of `_.assign` without support for multiple sources
    * or `customizer` functions.
    *
    * @private
    * @param {Object} object The destination object.
    * @param {Object} source The source object.
    * @returns {Object} Returns `object`.
    */
   function baseAssign(object, source) {
     return object && copyObject(source, keys(source), object);
   }
   /**
    * The base implementation of `_.assignIn` without support for multiple sources
    * or `customizer` functions.
    *
    * @private
    * @param {Object} object The destination object.
    * @param {Object} source The source object.
    * @returns {Object} Returns `object`.
    */
   function baseAssignIn(object, source) {
     return object && copyObject(source, keysIn(source), object);
   }
   /**
    * The base implementation of `assignValue` and `assignMergeValue` without
    * value checks.
    *
    * @private
    * @param {Object} object The object to modify.
    * @param {string} key The key of the property to assign.
    * @param {*} value The value to assign.
    */
   function baseAssignValue(object, key, value) {
     if (key == '__proto__' && defineProperty) {
       defineProperty(object, key, {
         'configurable': true,
         'enumerable': true,
         'value': value,
         'writable': true
       });
     } else {
       object[key] = value;
     }
   }
   /**
    * The base implementation of `_.at` without support for individual paths.
    *
    * @private
    * @param {Object} object The object to iterate over.
    * @param {string[]} paths The property paths to pick.
    * @returns {Array} Returns the picked elements.
    */
   function baseAt(object, paths) {
     var index = -1,
         length = paths.length,
         result = Array(length),
         skip = object == null;
     while (++index < length) {
       result[index] = skip ? undefined : get(object, paths[index]);
     }
     return result;
   }
   /**
    * The base implementation of `_.clamp` which doesn't coerce arguments.
    *
    * @private
    * @param {number} number The number to clamp.
    * @param {number} [lower] The lower bound.
    * @param {number} upper The upper bound.
    * @returns {number} Returns the clamped number.
    */
   function baseClamp(number, lower, upper) {
     if (number === number) {
       if (upper !== undefined) {
         number = number <= upper ? number : upper;
       }
       if (lower !== undefined) {
         number = number >= lower ? number : lower;
       }
     }
     return number;
   }
   /**
    * The base implementation of `_.clone` and `_.cloneDeep` which tracks
    * traversed objects.
    *
    * @private
    * @param {*} value The value to clone.
    * @param {boolean} bitmask The bitmask flags.
    *  1 - Deep clone
    *  2 - Flatten inherited properties
    *  4 - Clone symbols
    * @param {Function} [customizer] The function to customize cloning.
    * @param {string} [key] The key of `value`.
    * @param {Object} [object] The parent object of `value`.
    * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
    * @returns {*} Returns the cloned value.
    */
   function baseClone(value, bitmask, customizer, key, object, stack) {
     var result,
         isDeep = bitmask & CLONE_DEEP_FLAG,
         isFlat = bitmask & CLONE_FLAT_FLAG,
         isFull = bitmask & CLONE_SYMBOLS_FLAG;
     if (customizer) {
       result = object ? customizer(value, key, object, stack) : customizer(value);
     }
     if (result !== undefined) {
       return result;
     }
     if (!isObject(value)) {
       return value;
     }
     var isArr = isArray(value);
     if (isArr) {
       result = initCloneArray(value);
       if (!isDeep) {
         return copyArray(value, result);
       }
     } else {
       var tag = getTag(value),
           isFunc = tag == funcTag || tag == genTag;
       if (isBuffer(value)) {
         return cloneBuffer(value, isDeep);
       }
       if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
         result = (isFlat || isFunc) ? {} : initCloneObject(value);
         if (!isDeep) {
           return isFlat
             ? copySymbolsIn(value, baseAssignIn(result, value))
             : copySymbols(value, baseAssign(result, value));
         }
       } else {
         if (!cloneableTags[tag]) {
           return object ? value : {};
         }
         result = initCloneByTag(value, tag, isDeep);
       }
     }
     // Check for circular references and return its corresponding clone.
     stack || (stack = new Stack);
     var stacked = stack.get(value);
     if (stacked) {
       return stacked;
     }
     stack.set(value, result);
     if (isSet(value)) {
       value.forEach(function(subValue) {
         result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
       });
     } else if (isMap(value)) {
       value.forEach(function(subValue, key) {
         result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
       });
     }
     var keysFunc = isFull
       ? (isFlat ? getAllKeysIn : getAllKeys)
       : (isFlat ? keysIn : keys);
     var props = isArr ? undefined : keysFunc(value);
     arrayEach(props || value, function(subValue, key) {
       if (props) {
         key = subValue;
         subValue = value[key];
       }
       // Recursively populate clone (susceptible to call stack limits).
       assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
     });
     return result;
   }
   /**
    * The base implementation of `_.conforms` which doesn't clone `source`.
    *
    * @private
    * @param {Object} source The object of property predicates to conform to.
    * @returns {Function} Returns the new spec function.
    */
   function baseConforms(source) {
     var props = keys(source);
     return function(object) {
       return baseConformsTo(object, source, props);
     };
   }
   /**
    * The base implementation of `_.conformsTo` which accepts `props` to check.
    *
    * @private
    * @param {Object} object The object to inspect.
    * @param {Object} source The object of property predicates to conform to.
    * @returns {boolean} Returns `true` if `object` conforms, else `false`.
    */
   function baseConformsTo(object, source, props) {
     var length = props.length;
     if (object == null) {
       return !length;
     }
     object = Object(object);
     while (length--) {
       var key = props[length],
           predicate = source[key],
           value = object[key];
       if ((value === undefined && !(key in object)) || !predicate(value)) {
         return false;
       }
     }
     return true;
   }
   /**
    * The base implementation of `_.delay` and `_.defer` which accepts `args`
    * to provide to `func`.
    *
    * @private
    * @param {Function} func The function to delay.
    * @param {number} wait The number of milliseconds to delay invocation.
    * @param {Array} args The arguments to provide to `func`.
    * @returns {number|Object} Returns the timer id or timeout object.
    */
   function baseDelay(func, wait, args) {
     if (typeof func != 'function') {
       throw new TypeError(FUNC_ERROR_TEXT);
     }
     return setTimeout(function() { func.apply(undefined, args); }, wait);
   }
   /**
    * The base implementation of methods like `_.difference` without support
    * for excluding multiple arrays or iteratee shorthands.
    *
    * @private
    * @param {Array} array The array to inspect.
    * @param {Array} values The values to exclude.
    * @param {Function} [iteratee] The iteratee invoked per element.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns the new array of filtered values.
    */
   function baseDifference(array, values, iteratee, comparator) {
     var index = -1,
         includes = arrayIncludes,
         isCommon = true,
         length = array.length,
         result = [],
         valuesLength = values.length;
     if (!length) {
       return result;
     }
     if (iteratee) {
       values = arrayMap(values, baseUnary(iteratee));
     }
     if (comparator) {
       includes = arrayIncludesWith;
       isCommon = false;
     }
     else if (values.length >= LARGE_ARRAY_SIZE) {
       includes = cacheHas;
       isCommon = false;
       values = new SetCache(values);
     }
     outer:
     while (++index < length) {
       var value = array[index],
           computed = iteratee == null ? value : iteratee(value);
       value = (comparator || value !== 0) ? value : 0;
       if (isCommon && computed === computed) {
         var valuesIndex = valuesLength;
         while (valuesIndex--) {
           if (values[valuesIndex] === computed) {
             continue outer;
           }
         }
         result.push(value);
       }
       else if (!includes(values, computed, comparator)) {
         result.push(value);
       }
     }
     return result;
   }
   /**
    * The base implementation of `_.forEach` without support for iteratee shorthands.
    *
    * @private
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} iteratee The function invoked per iteration.
    * @returns {Array|Object} Returns `collection`.
    */
   var baseEach = createBaseEach(baseForOwn);
   /**
    * The base implementation of `_.forEachRight` without support for iteratee shorthands.
    *
    * @private
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} iteratee The function invoked per iteration.
    * @returns {Array|Object} Returns `collection`.
    */
   var baseEachRight = createBaseEach(baseForOwnRight, true);
   /**
    * The base implementation of `_.every` without support for iteratee shorthands.
    *
    * @private
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} predicate The function invoked per iteration.
    * @returns {boolean} Returns `true` if all elements pass the predicate check,
    *  else `false`
    */
   function baseEvery(collection, predicate) {
     var result = true;
     baseEach(collection, function(value, index, collection) {
       result = !!predicate(value, index, collection);
       return result;
     });
     return result;
   }
   /**
    * The base implementation of methods like `_.max` and `_.min` which accepts a
    * `comparator` to determine the extremum value.
    *
    * @private
    * @param {Array} array The array to iterate over.
    * @param {Function} iteratee The iteratee invoked per iteration.
    * @param {Function} comparator The comparator used to compare values.
    * @returns {*} Returns the extremum value.
    */
   function baseExtremum(array, iteratee, comparator) {
     var index = -1,
         length = array.length;
     while (++index < length) {
       var value = array[index],
           current = iteratee(value);
       if (current != null && (computed === undefined
             ? (current === current && !isSymbol(current))
             : comparator(current, computed)
           )) {
         var computed = current,
             result = value;
       }
     }
     return result;
   }
   /**
    * The base implementation of `_.fill` without an iteratee call guard.
    *
    * @private
    * @param {Array} array The array to fill.
    * @param {*} value The value to fill `array` with.
    * @param {number} [start=0] The start position.
    * @param {number} [end=array.length] The end position.
    * @returns {Array} Returns `array`.
    */
   function baseFill(array, value, start, end) {
     var length = array.length;
     start = toInteger(start);
     if (start < 0) {
       start = -start > length ? 0 : (length + start);
     }
     end = (end === undefined || end > length) ? length : toInteger(end);
     if (end < 0) {
       end += length;
     }
     end = start > end ? 0 : toLength(end);
     while (start < end) {
       array[start++] = value;
     }
     return array;
   }
   /**
    * The base implementation of `_.filter` without support for iteratee shorthands.
    *
    * @private
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} predicate The function invoked per iteration.
    * @returns {Array} Returns the new filtered array.
    */
   function baseFilter(collection, predicate) {
     var result = [];
     baseEach(collection, function(value, index, collection) {
       if (predicate(value, index, collection)) {
         result.push(value);
       }
     });
     return result;
   }
   /**
    * The base implementation of `_.flatten` with support for restricting flattening.
    *
    * @private
    * @param {Array} array The array to flatten.
    * @param {number} depth The maximum recursion depth.
    * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
    * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
    * @param {Array} [result=[]] The initial result value.
    * @returns {Array} Returns the new flattened array.
    */
   function baseFlatten(array, depth, predicate, isStrict, result) {
     var index = -1,
         length = array.length;
     predicate || (predicate = isFlattenable);
     result || (result = []);
     while (++index < length) {
       var value = array[index];
       if (depth > 0 && predicate(value)) {
         if (depth > 1) {
           // Recursively flatten arrays (susceptible to call stack limits).
           baseFlatten(value, depth - 1, predicate, isStrict, result);
         } else {
           arrayPush(result, value);
         }
       } else if (!isStrict) {
         result[result.length] = value;
       }
     }
     return result;
   }
   /**
    * The base implementation of `baseForOwn` which iterates over `object`
    * properties returned by `keysFunc` and invokes `iteratee` for each property.
    * Iteratee functions may exit iteration early by explicitly returning `false`.
    *
    * @private
    * @param {Object} object The object to iterate over.
    * @param {Function} iteratee The function invoked per iteration.
    * @param {Function} keysFunc The function to get the keys of `object`.
    * @returns {Object} Returns `object`.
    */
   var baseFor = createBaseFor();
   /**
    * This function is like `baseFor` except that it iterates over properties
    * in the opposite order.
    *
    * @private
    * @param {Object} object The object to iterate over.
    * @param {Function} iteratee The function invoked per iteration.
    * @param {Function} keysFunc The function to get the keys of `object`.
    * @returns {Object} Returns `object`.
    */
   var baseForRight = createBaseFor(true);
   /**
    * The base implementation of `_.forOwn` without support for iteratee shorthands.
    *
    * @private
    * @param {Object} object The object to iterate over.
    * @param {Function} iteratee The function invoked per iteration.
    * @returns {Object} Returns `object`.
    */
   function baseForOwn(object, iteratee) {
     return object && baseFor(object, iteratee, keys);
   }
   /**
    * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
    *
    * @private
    * @param {Object} object The object to iterate over.
    * @param {Function} iteratee The function invoked per iteration.
    * @returns {Object} Returns `object`.
    */
   function baseForOwnRight(object, iteratee) {
     return object && baseForRight(object, iteratee, keys);
   }
   /**
    * The base implementation of `_.functions` which creates an array of
    * `object` function property names filtered from `props`.
    *
    * @private
    * @param {Object} object The object to inspect.
    * @param {Array} props The property names to filter.
    * @returns {Array} Returns the function names.
    */
   function baseFunctions(object, props) {
     return arrayFilter(props, function(key) {
       return isFunction(object[key]);
     });
   }
   /**
    * The base implementation of `_.get` without support for default values.
    *
    * @private
    * @param {Object} object The object to query.
    * @param {Array|string} path The path of the property to get.
    * @returns {*} Returns the resolved value.
    */
   function baseGet(object, path) {
     path = castPath(path, object);
     var index = 0,
         length = path.length;
     while (object != null && index < length) {
       object = object[toKey(path[index++])];
     }
     return (index && index == length) ? object : undefined;
   }
   /**
    * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
    * `keysFunc` and `symbolsFunc` to get the enumerable property names and
    * symbols of `object`.
    *
    * @private
    * @param {Object} object The object to query.
    * @param {Function} keysFunc The function to get the keys of `object`.
    * @param {Function} symbolsFunc The function to get the symbols of `object`.
    * @returns {Array} Returns the array of property names and symbols.
    */
   function baseGetAllKeys(object, keysFunc, symbolsFunc) {
     var result = keysFunc(object);
     return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
   }
   /**
    * The base implementation of `getTag` without fallbacks for buggy environments.
    *
    * @private
    * @param {*} value The value to query.
    * @returns {string} Returns the `toStringTag`.
    */
   function baseGetTag(value) {
     if (value == null) {
       return value === undefined ? undefinedTag : nullTag;
     }
     return (symToStringTag && symToStringTag in Object(value))
       ? getRawTag(value)
       : objectToString(value);
   }
   /**
    * The base implementation of `_.gt` which doesn't coerce arguments.
    *
    * @private
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @returns {boolean} Returns `true` if `value` is greater than `other`,
    *  else `false`.
    */
   function baseGt(value, other) {
     return value > other;
   }
   /**
    * The base implementation of `_.has` without support for deep paths.
    *
    * @private
    * @param {Object} [object] The object to query.
    * @param {Array|string} key The key to check.
    * @returns {boolean} Returns `true` if `key` exists, else `false`.
    */
   function baseHas(object, key) {
     return object != null && hasOwnProperty.call(object, key);
   }
   /**
    * The base implementation of `_.hasIn` without support for deep paths.
    *
    * @private
    * @param {Object} [object] The object to query.
    * @param {Array|string} key The key to check.
    * @returns {boolean} Returns `true` if `key` exists, else `false`.
    */
   function baseHasIn(object, key) {
     return object != null && key in Object(object);
   }
   /**
    * The base implementation of `_.inRange` which doesn't coerce arguments.
    *
    * @private
    * @param {number} number The number to check.
    * @param {number} start The start of the range.
    * @param {number} end The end of the range.
    * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
    */
   function baseInRange(number, start, end) {
     return number >= nativeMin(start, end) && number < nativeMax(start, end);
   }
   /**
    * The base implementation of methods like `_.intersection`, without support
    * for iteratee shorthands, that accepts an array of arrays to inspect.
    *
    * @private
    * @param {Array} arrays The arrays to inspect.
    * @param {Function} [iteratee] The iteratee invoked per element.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns the new array of shared values.
    */
   function baseIntersection(arrays, iteratee, comparator) {
     var includes = comparator ? arrayIncludesWith : arrayIncludes,
         length = arrays[0].length,
         othLength = arrays.length,
         othIndex = othLength,
         caches = Array(othLength),
         maxLength = Infinity,
         result = [];
     while (othIndex--) {
       var array = arrays[othIndex];
       if (othIndex && iteratee) {
         array = arrayMap(array, baseUnary(iteratee));
       }
       maxLength = nativeMin(array.length, maxLength);
       caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
         ? new SetCache(othIndex && array)
         : undefined;
     }
     array = arrays[0];
     var index = -1,
         seen = caches[0];
     outer:
     while (++index < length && result.length < maxLength) {
       var value = array[index],
           computed = iteratee ? iteratee(value) : value;
       value = (comparator || value !== 0) ? value : 0;
       if (!(seen
             ? cacheHas(seen, computed)
             : includes(result, computed, comparator)
           )) {
         othIndex = othLength;
         while (--othIndex) {
           var cache = caches[othIndex];
           if (!(cache
                 ? cacheHas(cache, computed)
                 : includes(arrays[othIndex], computed, comparator))
               ) {
             continue outer;
           }
         }
         if (seen) {
           seen.push(computed);
         }
         result.push(value);
       }
     }
     return result;
   }
   /**
    * The base implementation of `_.invert` and `_.invertBy` which inverts
    * `object` with values transformed by `iteratee` and set by `setter`.
    *
    * @private
    * @param {Object} object The object to iterate over.
    * @param {Function} setter The function to set `accumulator` values.
    * @param {Function} iteratee The iteratee to transform values.
    * @param {Object} accumulator The initial inverted object.
    * @returns {Function} Returns `accumulator`.
    */
   function baseInverter(object, setter, iteratee, accumulator) {
     baseForOwn(object, function(value, key, object) {
       setter(accumulator, iteratee(value), key, object);
     });
     return accumulator;
   }
   /**
    * The base implementation of `_.invoke` without support for individual
    * method arguments.
    *
    * @private
    * @param {Object} object The object to query.
    * @param {Array|string} path The path of the method to invoke.
    * @param {Array} args The arguments to invoke the method with.
    * @returns {*} Returns the result of the invoked method.
    */
   function baseInvoke(object, path, args) {
     path = castPath(path, object);
     object = parent(object, path);
     var func = object == null ? object : object[toKey(last(path))];
     return func == null ? undefined : apply(func, object, args);
   }
   /**
    * The base implementation of `_.isArguments`.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is an `arguments` object,
    */
   function baseIsArguments(value) {
     return isObjectLike(value) && baseGetTag(value) == argsTag;
   }
   /**
    * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
    */
   function baseIsArrayBuffer(value) {
     return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
   }
   /**
    * The base implementation of `_.isDate` without Node.js optimizations.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
    */
   function baseIsDate(value) {
     return isObjectLike(value) && baseGetTag(value) == dateTag;
   }
   /**
    * The base implementation of `_.isEqual` which supports partial comparisons
    * and tracks traversed objects.
    *
    * @private
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @param {boolean} bitmask The bitmask flags.
    *  1 - Unordered comparison
    *  2 - Partial comparison
    * @param {Function} [customizer] The function to customize comparisons.
    * @param {Object} [stack] Tracks traversed `value` and `other` objects.
    * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
    */
   function baseIsEqual(value, other, bitmask, customizer, stack) {
     if (value === other) {
       return true;
     }
     if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
       return value !== value && other !== other;
     }
     return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
   }
   /**
    * A specialized version of `baseIsEqual` for arrays and objects which performs
    * deep comparisons and tracks traversed objects enabling objects with circular
    * references to be compared.
    *
    * @private
    * @param {Object} object The object to compare.
    * @param {Object} other The other object to compare.
    * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
    * @param {Function} customizer The function to customize comparisons.
    * @param {Function} equalFunc The function to determine equivalents of values.
    * @param {Object} [stack] Tracks traversed `object` and `other` objects.
    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
    */
   function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
     var objIsArr = isArray(object),
         othIsArr = isArray(other),
         objTag = objIsArr ? arrayTag : getTag(object),
         othTag = othIsArr ? arrayTag : getTag(other);
     objTag = objTag == argsTag ? objectTag : objTag;
     othTag = othTag == argsTag ? objectTag : othTag;
     var objIsObj = objTag == objectTag,
         othIsObj = othTag == objectTag,
         isSameTag = objTag == othTag;
     if (isSameTag && isBuffer(object)) {
       if (!isBuffer(other)) {
         return false;
       }
       objIsArr = true;
       objIsObj = false;
     }
     if (isSameTag && !objIsObj) {
       stack || (stack = new Stack);
       return (objIsArr || isTypedArray(object))
         ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
         : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
     }
     if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
       var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
           othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
       if (objIsWrapped || othIsWrapped) {
         var objUnwrapped = objIsWrapped ? object.value() : object,
             othUnwrapped = othIsWrapped ? other.value() : other;
         stack || (stack = new Stack);
         return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
       }
     }
     if (!isSameTag) {
       return false;
     }
     stack || (stack = new Stack);
     return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
   }
   /**
    * The base implementation of `_.isMap` without Node.js optimizations.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a map, else `false`.
    */
   function baseIsMap(value) {
     return isObjectLike(value) && getTag(value) == mapTag;
   }
   /**
    * The base implementation of `_.isMatch` without support for iteratee shorthands.
    *
    * @private
    * @param {Object} object The object to inspect.
    * @param {Object} source The object of property values to match.
    * @param {Array} matchData The property names, values, and compare flags to match.
    * @param {Function} [customizer] The function to customize comparisons.
    * @returns {boolean} Returns `true` if `object` is a match, else `false`.
    */
   function baseIsMatch(object, source, matchData, customizer) {
     var index = matchData.length,
         length = index,
         noCustomizer = !customizer;
     if (object == null) {
       return !length;
     }
     object = Object(object);
     while (index--) {
       var data = matchData[index];
       if ((noCustomizer && data[2])
             ? data[1] !== object[data[0]]
             : !(data[0] in object)
           ) {
         return false;
       }
     }
     while (++index < length) {
       data = matchData[index];
       var key = data[0],
           objValue = object[key],
           srcValue = data[1];
       if (noCustomizer && data[2]) {
         if (objValue === undefined && !(key in object)) {
           return false;
         }
       } else {
         var stack = new Stack;
         if (customizer) {
           var result = customizer(objValue, srcValue, key, object, source, stack);
         }
         if (!(result === undefined
               ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
               : result
             )) {
           return false;
         }
       }
     }
     return true;
   }
   /**
    * The base implementation of `_.isNative` without bad shim checks.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a native function,
    *  else `false`.
    */
   function baseIsNative(value) {
     if (!isObject(value) || isMasked(value)) {
       return false;
     }
     var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
     return pattern.test(toSource(value));
   }
   /**
    * The base implementation of `_.isRegExp` without Node.js optimizations.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
    */
   function baseIsRegExp(value) {
     return isObjectLike(value) && baseGetTag(value) == regexpTag;
   }
   /**
    * The base implementation of `_.isSet` without Node.js optimizations.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a set, else `false`.
    */
   function baseIsSet(value) {
     return isObjectLike(value) && getTag(value) == setTag;
   }
   /**
    * The base implementation of `_.isTypedArray` without Node.js optimizations.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
    */
   function baseIsTypedArray(value) {
     return isObjectLike(value) &&
       isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
   }
   /**
    * The base implementation of `_.iteratee`.
    *
    * @private
    * @param {*} [value=_.identity] The value to convert to an iteratee.
    * @returns {Function} Returns the iteratee.
    */
   function baseIteratee(value) {
     // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
     // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
     if (typeof value == 'function') {
       return value;
     }
     if (value == null) {
       return identity;
     }
     if (typeof value == 'object') {
       return isArray(value)
         ? baseMatchesProperty(value[0], value[1])
         : baseMatches(value);
     }
     return property(value);
   }
   /**
    * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
    *
    * @private
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of property names.
    */
   function baseKeys(object) {
     if (!isPrototype(object)) {
       return nativeKeys(object);
     }
     var result = [];
     for (var key in Object(object)) {
       if (hasOwnProperty.call(object, key) && key != 'constructor') {
         result.push(key);
       }
     }
     return result;
   }
   /**
    * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
    *
    * @private
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of property names.
    */
   function baseKeysIn(object) {
     if (!isObject(object)) {
       return nativeKeysIn(object);
     }
     var isProto = isPrototype(object),
         result = [];
     for (var key in object) {
       if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
         result.push(key);
       }
     }
     return result;
   }
   /**
    * The base implementation of `_.lt` which doesn't coerce arguments.
    *
    * @private
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @returns {boolean} Returns `true` if `value` is less than `other`,
    *  else `false`.
    */
   function baseLt(value, other) {
     return value < other;
   }
   /**
    * The base implementation of `_.map` without support for iteratee shorthands.
    *
    * @private
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} iteratee The function invoked per iteration.
    * @returns {Array} Returns the new mapped array.
    */
   function baseMap(collection, iteratee) {
     var index = -1,
         result = isArrayLike(collection) ? Array(collection.length) : [];
     baseEach(collection, function(value, key, collection) {
       result[++index] = iteratee(value, key, collection);
     });
     return result;
   }
   /**
    * The base implementation of `_.matches` which doesn't clone `source`.
    *
    * @private
    * @param {Object} source The object of property values to match.
    * @returns {Function} Returns the new spec function.
    */
   function baseMatches(source) {
     var matchData = getMatchData(source);
     if (matchData.length == 1 && matchData[0][2]) {
       return matchesStrictComparable(matchData[0][0], matchData[0][1]);
     }
     return function(object) {
       return object === source || baseIsMatch(object, source, matchData);
     };
   }
   /**
    * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
    *
    * @private
    * @param {string} path The path of the property to get.
    * @param {*} srcValue The value to match.
    * @returns {Function} Returns the new spec function.
    */
   function baseMatchesProperty(path, srcValue) {
     if (isKey(path) && isStrictComparable(srcValue)) {
       return matchesStrictComparable(toKey(path), srcValue);
     }
     return function(object) {
       var objValue = get(object, path);
       return (objValue === undefined && objValue === srcValue)
         ? hasIn(object, path)
         : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
     };
   }
   /**
    * The base implementation of `_.merge` without support for multiple sources.
    *
    * @private
    * @param {Object} object The destination object.
    * @param {Object} source The source object.
    * @param {number} srcIndex The index of `source`.
    * @param {Function} [customizer] The function to customize merged values.
    * @param {Object} [stack] Tracks traversed source values and their merged
    *  counterparts.
    */
   function baseMerge(object, source, srcIndex, customizer, stack) {
     if (object === source) {
       return;
     }
     baseFor(source, function(srcValue, key) {
       stack || (stack = new Stack);
       if (isObject(srcValue)) {
         baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
       }
       else {
         var newValue = customizer
           ? customizer(safeGet(object, key), srcValue, (key + ), object, source, stack)
           : undefined;
         if (newValue === undefined) {
           newValue = srcValue;
         }
         assignMergeValue(object, key, newValue);
       }
     }, keysIn);
   }
   /**
    * A specialized version of `baseMerge` for arrays and objects which performs
    * deep merges and tracks traversed objects enabling objects with circular
    * references to be merged.
    *
    * @private
    * @param {Object} object The destination object.
    * @param {Object} source The source object.
    * @param {string} key The key of the value to merge.
    * @param {number} srcIndex The index of `source`.
    * @param {Function} mergeFunc The function to merge values.
    * @param {Function} [customizer] The function to customize assigned values.
    * @param {Object} [stack] Tracks traversed source values and their merged
    *  counterparts.
    */
   function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
     var objValue = safeGet(object, key),
         srcValue = safeGet(source, key),
         stacked = stack.get(srcValue);
     if (stacked) {
       assignMergeValue(object, key, stacked);
       return;
     }
     var newValue = customizer
       ? customizer(objValue, srcValue, (key + ), object, source, stack)
       : undefined;
     var isCommon = newValue === undefined;
     if (isCommon) {
       var isArr = isArray(srcValue),
           isBuff = !isArr && isBuffer(srcValue),
           isTyped = !isArr && !isBuff && isTypedArray(srcValue);
       newValue = srcValue;
       if (isArr || isBuff || isTyped) {
         if (isArray(objValue)) {
           newValue = objValue;
         }
         else if (isArrayLikeObject(objValue)) {
           newValue = copyArray(objValue);
         }
         else if (isBuff) {
           isCommon = false;
           newValue = cloneBuffer(srcValue, true);
         }
         else if (isTyped) {
           isCommon = false;
           newValue = cloneTypedArray(srcValue, true);
         }
         else {
           newValue = [];
         }
       }
       else if (isPlainObject(srcValue) || isArguments(srcValue)) {
         newValue = objValue;
         if (isArguments(objValue)) {
           newValue = toPlainObject(objValue);
         }
         else if (!isObject(objValue) || isFunction(objValue)) {
           newValue = initCloneObject(srcValue);
         }
       }
       else {
         isCommon = false;
       }
     }
     if (isCommon) {
       // Recursively merge objects and arrays (susceptible to call stack limits).
       stack.set(srcValue, newValue);
       mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
       stack['delete'](srcValue);
     }
     assignMergeValue(object, key, newValue);
   }
   /**
    * The base implementation of `_.nth` which doesn't coerce arguments.
    *
    * @private
    * @param {Array} array The array to query.
    * @param {number} n The index of the element to return.
    * @returns {*} Returns the nth element of `array`.
    */
   function baseNth(array, n) {
     var length = array.length;
     if (!length) {
       return;
     }
     n += n < 0 ? length : 0;
     return isIndex(n, length) ? array[n] : undefined;
   }
   /**
    * The base implementation of `_.orderBy` without param guards.
    *
    * @private
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
    * @param {string[]} orders The sort orders of `iteratees`.
    * @returns {Array} Returns the new sorted array.
    */
   function baseOrderBy(collection, iteratees, orders) {
     var index = -1;
     iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee()));
     var result = baseMap(collection, function(value, key, collection) {
       var criteria = arrayMap(iteratees, function(iteratee) {
         return iteratee(value);
       });
       return { 'criteria': criteria, 'index': ++index, 'value': value };
     });
     return baseSortBy(result, function(object, other) {
       return compareMultiple(object, other, orders);
     });
   }
   /**
    * The base implementation of `_.pick` without support for individual
    * property identifiers.
    *
    * @private
    * @param {Object} object The source object.
    * @param {string[]} paths The property paths to pick.
    * @returns {Object} Returns the new object.
    */
   function basePick(object, paths) {
     return basePickBy(object, paths, function(value, path) {
       return hasIn(object, path);
     });
   }
   /**
    * The base implementation of  `_.pickBy` without support for iteratee shorthands.
    *
    * @private
    * @param {Object} object The source object.
    * @param {string[]} paths The property paths to pick.
    * @param {Function} predicate The function invoked per property.
    * @returns {Object} Returns the new object.
    */
   function basePickBy(object, paths, predicate) {
     var index = -1,
         length = paths.length,
         result = {};
     while (++index < length) {
       var path = paths[index],
           value = baseGet(object, path);
       if (predicate(value, path)) {
         baseSet(result, castPath(path, object), value);
       }
     }
     return result;
   }
   /**
    * A specialized version of `baseProperty` which supports deep paths.
    *
    * @private
    * @param {Array|string} path The path of the property to get.
    * @returns {Function} Returns the new accessor function.
    */
   function basePropertyDeep(path) {
     return function(object) {
       return baseGet(object, path);
     };
   }
   /**
    * The base implementation of `_.pullAllBy` without support for iteratee
    * shorthands.
    *
    * @private
    * @param {Array} array The array to modify.
    * @param {Array} values The values to remove.
    * @param {Function} [iteratee] The iteratee invoked per element.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns `array`.
    */
   function basePullAll(array, values, iteratee, comparator) {
     var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
         index = -1,
         length = values.length,
         seen = array;
     if (array === values) {
       values = copyArray(values);
     }
     if (iteratee) {
       seen = arrayMap(array, baseUnary(iteratee));
     }
     while (++index < length) {
       var fromIndex = 0,
           value = values[index],
           computed = iteratee ? iteratee(value) : value;
       while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
         if (seen !== array) {
           splice.call(seen, fromIndex, 1);
         }
         splice.call(array, fromIndex, 1);
       }
     }
     return array;
   }
   /**
    * The base implementation of `_.pullAt` without support for individual
    * indexes or capturing the removed elements.
    *
    * @private
    * @param {Array} array The array to modify.
    * @param {number[]} indexes The indexes of elements to remove.
    * @returns {Array} Returns `array`.
    */
   function basePullAt(array, indexes) {
     var length = array ? indexes.length : 0,
         lastIndex = length - 1;
     while (length--) {
       var index = indexes[length];
       if (length == lastIndex || index !== previous) {
         var previous = index;
         if (isIndex(index)) {
           splice.call(array, index, 1);
         } else {
           baseUnset(array, index);
         }
       }
     }
     return array;
   }
   /**
    * The base implementation of `_.random` without support for returning
    * floating-point numbers.
    *
    * @private
    * @param {number} lower The lower bound.
    * @param {number} upper The upper bound.
    * @returns {number} Returns the random number.
    */
   function baseRandom(lower, upper) {
     return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
   }
   /**
    * The base implementation of `_.range` and `_.rangeRight` which doesn't
    * coerce arguments.
    *
    * @private
    * @param {number} start The start of the range.
    * @param {number} end The end of the range.
    * @param {number} step The value to increment or decrement by.
    * @param {boolean} [fromRight] Specify iterating from right to left.
    * @returns {Array} Returns the range of numbers.
    */
   function baseRange(start, end, step, fromRight) {
     var index = -1,
         length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
         result = Array(length);
     while (length--) {
       result[fromRight ? length : ++index] = start;
       start += step;
     }
     return result;
   }
   /**
    * The base implementation of `_.repeat` which doesn't coerce arguments.
    *
    * @private
    * @param {string} string The string to repeat.
    * @param {number} n The number of times to repeat the string.
    * @returns {string} Returns the repeated string.
    */
   function baseRepeat(string, n) {
     var result = ;
     if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
       return result;
     }
     // Leverage the exponentiation by squaring algorithm for a faster repeat.
     // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
     do {
       if (n % 2) {
         result += string;
       }
       n = nativeFloor(n / 2);
       if (n) {
         string += string;
       }
     } while (n);
     return result;
   }
   /**
    * The base implementation of `_.rest` which doesn't validate or coerce arguments.
    *
    * @private
    * @param {Function} func The function to apply a rest parameter to.
    * @param {number} [start=func.length-1] The start position of the rest parameter.
    * @returns {Function} Returns the new function.
    */
   function baseRest(func, start) {
     return setToString(overRest(func, start, identity), func + );
   }
   /**
    * The base implementation of `_.sample`.
    *
    * @private
    * @param {Array|Object} collection The collection to sample.
    * @returns {*} Returns the random element.
    */
   function baseSample(collection) {
     return arraySample(values(collection));
   }
   /**
    * The base implementation of `_.sampleSize` without param guards.
    *
    * @private
    * @param {Array|Object} collection The collection to sample.
    * @param {number} n The number of elements to sample.
    * @returns {Array} Returns the random elements.
    */
   function baseSampleSize(collection, n) {
     var array = values(collection);
     return shuffleSelf(array, baseClamp(n, 0, array.length));
   }
   /**
    * The base implementation of `_.set`.
    *
    * @private
    * @param {Object} object The object to modify.
    * @param {Array|string} path The path of the property to set.
    * @param {*} value The value to set.
    * @param {Function} [customizer] The function to customize path creation.
    * @returns {Object} Returns `object`.
    */
   function baseSet(object, path, value, customizer) {
     if (!isObject(object)) {
       return object;
     }
     path = castPath(path, object);
     var index = -1,
         length = path.length,
         lastIndex = length - 1,
         nested = object;
     while (nested != null && ++index < length) {
       var key = toKey(path[index]),
           newValue = value;
       if (index != lastIndex) {
         var objValue = nested[key];
         newValue = customizer ? customizer(objValue, key, nested) : undefined;
         if (newValue === undefined) {
           newValue = isObject(objValue)
             ? objValue
             : (isIndex(path[index + 1]) ? [] : {});
         }
       }
       assignValue(nested, key, newValue);
       nested = nested[key];
     }
     return object;
   }
   /**
    * The base implementation of `setData` without support for hot loop shorting.
    *
    * @private
    * @param {Function} func The function to associate metadata with.
    * @param {*} data The metadata.
    * @returns {Function} Returns `func`.
    */
   var baseSetData = !metaMap ? identity : function(func, data) {
     metaMap.set(func, data);
     return func;
   };
   /**
    * The base implementation of `setToString` without support for hot loop shorting.
    *
    * @private
    * @param {Function} func The function to modify.
    * @param {Function} string The `toString` result.
    * @returns {Function} Returns `func`.
    */
   var baseSetToString = !defineProperty ? identity : function(func, string) {
     return defineProperty(func, 'toString', {
       'configurable': true,
       'enumerable': false,
       'value': constant(string),
       'writable': true
     });
   };
   /**
    * The base implementation of `_.shuffle`.
    *
    * @private
    * @param {Array|Object} collection The collection to shuffle.
    * @returns {Array} Returns the new shuffled array.
    */
   function baseShuffle(collection) {
     return shuffleSelf(values(collection));
   }
   /**
    * The base implementation of `_.slice` without an iteratee call guard.
    *
    * @private
    * @param {Array} array The array to slice.
    * @param {number} [start=0] The start position.
    * @param {number} [end=array.length] The end position.
    * @returns {Array} Returns the slice of `array`.
    */
   function baseSlice(array, start, end) {
     var index = -1,
         length = array.length;
     if (start < 0) {
       start = -start > length ? 0 : (length + start);
     }
     end = end > length ? length : end;
     if (end < 0) {
       end += length;
     }
     length = start > end ? 0 : ((end - start) >>> 0);
     start >>>= 0;
     var result = Array(length);
     while (++index < length) {
       result[index] = array[index + start];
     }
     return result;
   }
   /**
    * The base implementation of `_.some` without support for iteratee shorthands.
    *
    * @private
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} predicate The function invoked per iteration.
    * @returns {boolean} Returns `true` if any element passes the predicate check,
    *  else `false`.
    */
   function baseSome(collection, predicate) {
     var result;
     baseEach(collection, function(value, index, collection) {
       result = predicate(value, index, collection);
       return !result;
     });
     return !!result;
   }
   /**
    * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
    * performs a binary search of `array` to determine the index at which `value`
    * should be inserted into `array` in order to maintain its sort order.
    *
    * @private
    * @param {Array} array The sorted array to inspect.
    * @param {*} value The value to evaluate.
    * @param {boolean} [retHighest] Specify returning the highest qualified index.
    * @returns {number} Returns the index at which `value` should be inserted
    *  into `array`.
    */
   function baseSortedIndex(array, value, retHighest) {
     var low = 0,
         high = array == null ? low : array.length;
     if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
       while (low < high) {
         var mid = (low + high) >>> 1,
             computed = array[mid];
         if (computed !== null && !isSymbol(computed) &&
             (retHighest ? (computed <= value) : (computed < value))) {
           low = mid + 1;
         } else {
           high = mid;
         }
       }
       return high;
     }
     return baseSortedIndexBy(array, value, identity, retHighest);
   }
   /**
    * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
    * which invokes `iteratee` for `value` and each element of `array` to compute
    * their sort ranking. The iteratee is invoked with one argument; (value).
    *
    * @private
    * @param {Array} array The sorted array to inspect.
    * @param {*} value The value to evaluate.
    * @param {Function} iteratee The iteratee invoked per element.
    * @param {boolean} [retHighest] Specify returning the highest qualified index.
    * @returns {number} Returns the index at which `value` should be inserted
    *  into `array`.
    */
   function baseSortedIndexBy(array, value, iteratee, retHighest) {
     value = iteratee(value);
     var low = 0,
         high = array == null ? 0 : array.length,
         valIsNaN = value !== value,
         valIsNull = value === null,
         valIsSymbol = isSymbol(value),
         valIsUndefined = value === undefined;
     while (low < high) {
       var mid = nativeFloor((low + high) / 2),
           computed = iteratee(array[mid]),
           othIsDefined = computed !== undefined,
           othIsNull = computed === null,
           othIsReflexive = computed === computed,
           othIsSymbol = isSymbol(computed);
       if (valIsNaN) {
         var setLow = retHighest || othIsReflexive;
       } else if (valIsUndefined) {
         setLow = othIsReflexive && (retHighest || othIsDefined);
       } else if (valIsNull) {
         setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
       } else if (valIsSymbol) {
         setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
       } else if (othIsNull || othIsSymbol) {
         setLow = false;
       } else {
         setLow = retHighest ? (computed <= value) : (computed < value);
       }
       if (setLow) {
         low = mid + 1;
       } else {
         high = mid;
       }
     }
     return nativeMin(high, MAX_ARRAY_INDEX);
   }
   /**
    * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
    * support for iteratee shorthands.
    *
    * @private
    * @param {Array} array The array to inspect.
    * @param {Function} [iteratee] The iteratee invoked per element.
    * @returns {Array} Returns the new duplicate free array.
    */
   function baseSortedUniq(array, iteratee) {
     var index = -1,
         length = array.length,
         resIndex = 0,
         result = [];
     while (++index < length) {
       var value = array[index],
           computed = iteratee ? iteratee(value) : value;
       if (!index || !eq(computed, seen)) {
         var seen = computed;
         result[resIndex++] = value === 0 ? 0 : value;
       }
     }
     return result;
   }
   /**
    * The base implementation of `_.toNumber` which doesn't ensure correct
    * conversions of binary, hexadecimal, or octal string values.
    *
    * @private
    * @param {*} value The value to process.
    * @returns {number} Returns the number.
    */
   function baseToNumber(value) {
     if (typeof value == 'number') {
       return value;
     }
     if (isSymbol(value)) {
       return NAN;
     }
     return +value;
   }
   /**
    * The base implementation of `_.toString` which doesn't convert nullish
    * values to empty strings.
    *
    * @private
    * @param {*} value The value to process.
    * @returns {string} Returns the string.
    */
   function baseToString(value) {
     // Exit early for strings to avoid a performance hit in some environments.
     if (typeof value == 'string') {
       return value;
     }
     if (isArray(value)) {
       // Recursively convert values (susceptible to call stack limits).
       return arrayMap(value, baseToString) + ;
     }
     if (isSymbol(value)) {
       return symbolToString ? symbolToString.call(value) : ;
     }
     var result = (value + );
     return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
   }
   /**
    * The base implementation of `_.uniqBy` without support for iteratee shorthands.
    *
    * @private
    * @param {Array} array The array to inspect.
    * @param {Function} [iteratee] The iteratee invoked per element.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns the new duplicate free array.
    */
   function baseUniq(array, iteratee, comparator) {
     var index = -1,
         includes = arrayIncludes,
         length = array.length,
         isCommon = true,
         result = [],
         seen = result;
     if (comparator) {
       isCommon = false;
       includes = arrayIncludesWith;
     }
     else if (length >= LARGE_ARRAY_SIZE) {
       var set = iteratee ? null : createSet(array);
       if (set) {
         return setToArray(set);
       }
       isCommon = false;
       includes = cacheHas;
       seen = new SetCache;
     }
     else {
       seen = iteratee ? [] : result;
     }
     outer:
     while (++index < length) {
       var value = array[index],
           computed = iteratee ? iteratee(value) : value;
       value = (comparator || value !== 0) ? value : 0;
       if (isCommon && computed === computed) {
         var seenIndex = seen.length;
         while (seenIndex--) {
           if (seen[seenIndex] === computed) {
             continue outer;
           }
         }
         if (iteratee) {
           seen.push(computed);
         }
         result.push(value);
       }
       else if (!includes(seen, computed, comparator)) {
         if (seen !== result) {
           seen.push(computed);
         }
         result.push(value);
       }
     }
     return result;
   }
   /**
    * The base implementation of `_.unset`.
    *
    * @private
    * @param {Object} object The object to modify.
    * @param {Array|string} path The property path to unset.
    * @returns {boolean} Returns `true` if the property is deleted, else `false`.
    */
   function baseUnset(object, path) {
     path = castPath(path, object);
     object = parent(object, path);
     return object == null || delete object[toKey(last(path))];
   }
   /**
    * The base implementation of `_.update`.
    *
    * @private
    * @param {Object} object The object to modify.
    * @param {Array|string} path The path of the property to update.
    * @param {Function} updater The function to produce the updated value.
    * @param {Function} [customizer] The function to customize path creation.
    * @returns {Object} Returns `object`.
    */
   function baseUpdate(object, path, updater, customizer) {
     return baseSet(object, path, updater(baseGet(object, path)), customizer);
   }
   /**
    * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
    * without support for iteratee shorthands.
    *
    * @private
    * @param {Array} array The array to query.
    * @param {Function} predicate The function invoked per iteration.
    * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
    * @param {boolean} [fromRight] Specify iterating from right to left.
    * @returns {Array} Returns the slice of `array`.
    */
   function baseWhile(array, predicate, isDrop, fromRight) {
     var length = array.length,
         index = fromRight ? length : -1;
     while ((fromRight ? index-- : ++index < length) &&
       predicate(array[index], index, array)) {}
     return isDrop
       ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
       : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
   }
   /**
    * The base implementation of `wrapperValue` which returns the result of
    * performing a sequence of actions on the unwrapped `value`, where each
    * successive action is supplied the return value of the previous.
    *
    * @private
    * @param {*} value The unwrapped value.
    * @param {Array} actions Actions to perform to resolve the unwrapped value.
    * @returns {*} Returns the resolved value.
    */
   function baseWrapperValue(value, actions) {
     var result = value;
     if (result instanceof LazyWrapper) {
       result = result.value();
     }
     return arrayReduce(actions, function(result, action) {
       return action.func.apply(action.thisArg, arrayPush([result], action.args));
     }, result);
   }
   /**
    * The base implementation of methods like `_.xor`, without support for
    * iteratee shorthands, that accepts an array of arrays to inspect.
    *
    * @private
    * @param {Array} arrays The arrays to inspect.
    * @param {Function} [iteratee] The iteratee invoked per element.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns the new array of values.
    */
   function baseXor(arrays, iteratee, comparator) {
     var length = arrays.length;
     if (length < 2) {
       return length ? baseUniq(arrays[0]) : [];
     }
     var index = -1,
         result = Array(length);
     while (++index < length) {
       var array = arrays[index],
           othIndex = -1;
       while (++othIndex < length) {
         if (othIndex != index) {
           result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
         }
       }
     }
     return baseUniq(baseFlatten(result, 1), iteratee, comparator);
   }
   /**
    * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
    *
    * @private
    * @param {Array} props The property identifiers.
    * @param {Array} values The property values.
    * @param {Function} assignFunc The function to assign values.
    * @returns {Object} Returns the new object.
    */
   function baseZipObject(props, values, assignFunc) {
     var index = -1,
         length = props.length,
         valsLength = values.length,
         result = {};
     while (++index < length) {
       var value = index < valsLength ? values[index] : undefined;
       assignFunc(result, props[index], value);
     }
     return result;
   }
   /**
    * Casts `value` to an empty array if it's not an array like object.
    *
    * @private
    * @param {*} value The value to inspect.
    * @returns {Array|Object} Returns the cast array-like object.
    */
   function castArrayLikeObject(value) {
     return isArrayLikeObject(value) ? value : [];
   }
   /**
    * Casts `value` to `identity` if it's not a function.
    *
    * @private
    * @param {*} value The value to inspect.
    * @returns {Function} Returns cast function.
    */
   function castFunction(value) {
     return typeof value == 'function' ? value : identity;
   }
   /**
    * Casts `value` to a path array if it's not one.
    *
    * @private
    * @param {*} value The value to inspect.
    * @param {Object} [object] The object to query keys on.
    * @returns {Array} Returns the cast property path array.
    */
   function castPath(value, object) {
     if (isArray(value)) {
       return value;
     }
     return isKey(value, object) ? [value] : stringToPath(toString(value));
   }
   /**
    * A `baseRest` alias which can be replaced with `identity` by module
    * replacement plugins.
    *
    * @private
    * @type {Function}
    * @param {Function} func The function to apply a rest parameter to.
    * @returns {Function} Returns the new function.
    */
   var castRest = baseRest;
   /**
    * Casts `array` to a slice if it's needed.
    *
    * @private
    * @param {Array} array The array to inspect.
    * @param {number} start The start position.
    * @param {number} [end=array.length] The end position.
    * @returns {Array} Returns the cast slice.
    */
   function castSlice(array, start, end) {
     var length = array.length;
     end = end === undefined ? length : end;
     return (!start && end >= length) ? array : baseSlice(array, start, end);
   }
   /**
    * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
    *
    * @private
    * @param {number|Object} id The timer id or timeout object of the timer to clear.
    */
   var clearTimeout = ctxClearTimeout || function(id) {
     return root.clearTimeout(id);
   };
   /**
    * Creates a clone of  `buffer`.
    *
    * @private
    * @param {Buffer} buffer The buffer to clone.
    * @param {boolean} [isDeep] Specify a deep clone.
    * @returns {Buffer} Returns the cloned buffer.
    */
   function cloneBuffer(buffer, isDeep) {
     if (isDeep) {
       return buffer.slice();
     }
     var length = buffer.length,
         result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
     buffer.copy(result);
     return result;
   }
   /**
    * Creates a clone of `arrayBuffer`.
    *
    * @private
    * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
    * @returns {ArrayBuffer} Returns the cloned array buffer.
    */
   function cloneArrayBuffer(arrayBuffer) {
     var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
     new Uint8Array(result).set(new Uint8Array(arrayBuffer));
     return result;
   }
   /**
    * Creates a clone of `dataView`.
    *
    * @private
    * @param {Object} dataView The data view to clone.
    * @param {boolean} [isDeep] Specify a deep clone.
    * @returns {Object} Returns the cloned data view.
    */
   function cloneDataView(dataView, isDeep) {
     var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
     return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
   }
   /**
    * Creates a clone of `regexp`.
    *
    * @private
    * @param {Object} regexp The regexp to clone.
    * @returns {Object} Returns the cloned regexp.
    */
   function cloneRegExp(regexp) {
     var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
     result.lastIndex = regexp.lastIndex;
     return result;
   }
   /**
    * Creates a clone of the `symbol` object.
    *
    * @private
    * @param {Object} symbol The symbol object to clone.
    * @returns {Object} Returns the cloned symbol object.
    */
   function cloneSymbol(symbol) {
     return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
   }
   /**
    * Creates a clone of `typedArray`.
    *
    * @private
    * @param {Object} typedArray The typed array to clone.
    * @param {boolean} [isDeep] Specify a deep clone.
    * @returns {Object} Returns the cloned typed array.
    */
   function cloneTypedArray(typedArray, isDeep) {
     var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
     return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
   }
   /**
    * Compares values to sort them in ascending order.
    *
    * @private
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @returns {number} Returns the sort order indicator for `value`.
    */
   function compareAscending(value, other) {
     if (value !== other) {
       var valIsDefined = value !== undefined,
           valIsNull = value === null,
           valIsReflexive = value === value,
           valIsSymbol = isSymbol(value);
       var othIsDefined = other !== undefined,
           othIsNull = other === null,
           othIsReflexive = other === other,
           othIsSymbol = isSymbol(other);
       if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
           (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
           (valIsNull && othIsDefined && othIsReflexive) ||
           (!valIsDefined && othIsReflexive) ||
           !valIsReflexive) {
         return 1;
       }
       if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
           (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
           (othIsNull && valIsDefined && valIsReflexive) ||
           (!othIsDefined && valIsReflexive) ||
           !othIsReflexive) {
         return -1;
       }
     }
     return 0;
   }
   /**
    * Used by `_.orderBy` to compare multiple properties of a value to another
    * and stable sort them.
    *
    * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
    * specify an order of "desc" for descending or "asc" for ascending sort order
    * of corresponding values.
    *
    * @private
    * @param {Object} object The object to compare.
    * @param {Object} other The other object to compare.
    * @param {boolean[]|string[]} orders The order to sort by for each property.
    * @returns {number} Returns the sort order indicator for `object`.
    */
   function compareMultiple(object, other, orders) {
     var index = -1,
         objCriteria = object.criteria,
         othCriteria = other.criteria,
         length = objCriteria.length,
         ordersLength = orders.length;
     while (++index < length) {
       var result = compareAscending(objCriteria[index], othCriteria[index]);
       if (result) {
         if (index >= ordersLength) {
           return result;
         }
         var order = orders[index];
         return result * (order == 'desc' ? -1 : 1);
       }
     }
     // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
     // that causes it, under certain circumstances, to provide the same value for
     // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
     // for more details.
     //
     // This also ensures a stable sort in V8 and other engines.
     // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
     return object.index - other.index;
   }
   /**
    * Creates an array that is the composition of partially applied arguments,
    * placeholders, and provided arguments into a single array of arguments.
    *
    * @private
    * @param {Array} args The provided arguments.
    * @param {Array} partials The arguments to prepend to those provided.
    * @param {Array} holders The `partials` placeholder indexes.
    * @params {boolean} [isCurried] Specify composing for a curried function.
    * @returns {Array} Returns the new array of composed arguments.
    */
   function composeArgs(args, partials, holders, isCurried) {
     var argsIndex = -1,
         argsLength = args.length,
         holdersLength = holders.length,
         leftIndex = -1,
         leftLength = partials.length,
         rangeLength = nativeMax(argsLength - holdersLength, 0),
         result = Array(leftLength + rangeLength),
         isUncurried = !isCurried;
     while (++leftIndex < leftLength) {
       result[leftIndex] = partials[leftIndex];
     }
     while (++argsIndex < holdersLength) {
       if (isUncurried || argsIndex < argsLength) {
         result[holders[argsIndex]] = args[argsIndex];
       }
     }
     while (rangeLength--) {
       result[leftIndex++] = args[argsIndex++];
     }
     return result;
   }
   /**
    * This function is like `composeArgs` except that the arguments composition
    * is tailored for `_.partialRight`.
    *
    * @private
    * @param {Array} args The provided arguments.
    * @param {Array} partials The arguments to append to those provided.
    * @param {Array} holders The `partials` placeholder indexes.
    * @params {boolean} [isCurried] Specify composing for a curried function.
    * @returns {Array} Returns the new array of composed arguments.
    */
   function composeArgsRight(args, partials, holders, isCurried) {
     var argsIndex = -1,
         argsLength = args.length,
         holdersIndex = -1,
         holdersLength = holders.length,
         rightIndex = -1,
         rightLength = partials.length,
         rangeLength = nativeMax(argsLength - holdersLength, 0),
         result = Array(rangeLength + rightLength),
         isUncurried = !isCurried;
     while (++argsIndex < rangeLength) {
       result[argsIndex] = args[argsIndex];
     }
     var offset = argsIndex;
     while (++rightIndex < rightLength) {
       result[offset + rightIndex] = partials[rightIndex];
     }
     while (++holdersIndex < holdersLength) {
       if (isUncurried || argsIndex < argsLength) {
         result[offset + holders[holdersIndex]] = args[argsIndex++];
       }
     }
     return result;
   }
   /**
    * Copies the values of `source` to `array`.
    *
    * @private
    * @param {Array} source The array to copy values from.
    * @param {Array} [array=[]] The array to copy values to.
    * @returns {Array} Returns `array`.
    */
   function copyArray(source, array) {
     var index = -1,
         length = source.length;
     array || (array = Array(length));
     while (++index < length) {
       array[index] = source[index];
     }
     return array;
   }
   /**
    * Copies properties of `source` to `object`.
    *
    * @private
    * @param {Object} source The object to copy properties from.
    * @param {Array} props The property identifiers to copy.
    * @param {Object} [object={}] The object to copy properties to.
    * @param {Function} [customizer] The function to customize copied values.
    * @returns {Object} Returns `object`.
    */
   function copyObject(source, props, object, customizer) {
     var isNew = !object;
     object || (object = {});
     var index = -1,
         length = props.length;
     while (++index < length) {
       var key = props[index];
       var newValue = customizer
         ? customizer(object[key], source[key], key, object, source)
         : undefined;
       if (newValue === undefined) {
         newValue = source[key];
       }
       if (isNew) {
         baseAssignValue(object, key, newValue);
       } else {
         assignValue(object, key, newValue);
       }
     }
     return object;
   }
   /**
    * Copies own symbols of `source` to `object`.
    *
    * @private
    * @param {Object} source The object to copy symbols from.
    * @param {Object} [object={}] The object to copy symbols to.
    * @returns {Object} Returns `object`.
    */
   function copySymbols(source, object) {
     return copyObject(source, getSymbols(source), object);
   }
   /**
    * Copies own and inherited symbols of `source` to `object`.
    *
    * @private
    * @param {Object} source The object to copy symbols from.
    * @param {Object} [object={}] The object to copy symbols to.
    * @returns {Object} Returns `object`.
    */
   function copySymbolsIn(source, object) {
     return copyObject(source, getSymbolsIn(source), object);
   }
   /**
    * Creates a function like `_.groupBy`.
    *
    * @private
    * @param {Function} setter The function to set accumulator values.
    * @param {Function} [initializer] The accumulator object initializer.
    * @returns {Function} Returns the new aggregator function.
    */
   function createAggregator(setter, initializer) {
     return function(collection, iteratee) {
       var func = isArray(collection) ? arrayAggregator : baseAggregator,
           accumulator = initializer ? initializer() : {};
       return func(collection, setter, getIteratee(iteratee, 2), accumulator);
     };
   }
   /**
    * Creates a function like `_.assign`.
    *
    * @private
    * @param {Function} assigner The function to assign values.
    * @returns {Function} Returns the new assigner function.
    */
   function createAssigner(assigner) {
     return baseRest(function(object, sources) {
       var index = -1,
           length = sources.length,
           customizer = length > 1 ? sources[length - 1] : undefined,
           guard = length > 2 ? sources[2] : undefined;
       customizer = (assigner.length > 3 && typeof customizer == 'function')
         ? (length--, customizer)
         : undefined;
       if (guard && isIterateeCall(sources[0], sources[1], guard)) {
         customizer = length < 3 ? undefined : customizer;
         length = 1;
       }
       object = Object(object);
       while (++index < length) {
         var source = sources[index];
         if (source) {
           assigner(object, source, index, customizer);
         }
       }
       return object;
     });
   }
   /**
    * Creates a `baseEach` or `baseEachRight` function.
    *
    * @private
    * @param {Function} eachFunc The function to iterate over a collection.
    * @param {boolean} [fromRight] Specify iterating from right to left.
    * @returns {Function} Returns the new base function.
    */
   function createBaseEach(eachFunc, fromRight) {
     return function(collection, iteratee) {
       if (collection == null) {
         return collection;
       }
       if (!isArrayLike(collection)) {
         return eachFunc(collection, iteratee);
       }
       var length = collection.length,
           index = fromRight ? length : -1,
           iterable = Object(collection);
       while ((fromRight ? index-- : ++index < length)) {
         if (iteratee(iterable[index], index, iterable) === false) {
           break;
         }
       }
       return collection;
     };
   }
   /**
    * Creates a base function for methods like `_.forIn` and `_.forOwn`.
    *
    * @private
    * @param {boolean} [fromRight] Specify iterating from right to left.
    * @returns {Function} Returns the new base function.
    */
   function createBaseFor(fromRight) {
     return function(object, iteratee, keysFunc) {
       var index = -1,
           iterable = Object(object),
           props = keysFunc(object),
           length = props.length;
       while (length--) {
         var key = props[fromRight ? length : ++index];
         if (iteratee(iterable[key], key, iterable) === false) {
           break;
         }
       }
       return object;
     };
   }
   /**
    * Creates a function that wraps `func` to invoke it with the optional `this`
    * binding of `thisArg`.
    *
    * @private
    * @param {Function} func The function to wrap.
    * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
    * @param {*} [thisArg] The `this` binding of `func`.
    * @returns {Function} Returns the new wrapped function.
    */
   function createBind(func, bitmask, thisArg) {
     var isBind = bitmask & WRAP_BIND_FLAG,
         Ctor = createCtor(func);
     function wrapper() {
       var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
       return fn.apply(isBind ? thisArg : this, arguments);
     }
     return wrapper;
   }
   /**
    * Creates a function like `_.lowerFirst`.
    *
    * @private
    * @param {string} methodName The name of the `String` case method to use.
    * @returns {Function} Returns the new case function.
    */
   function createCaseFirst(methodName) {
     return function(string) {
       string = toString(string);
       var strSymbols = hasUnicode(string)
         ? stringToArray(string)
         : undefined;
       var chr = strSymbols
         ? strSymbols[0]
         : string.charAt(0);
       var trailing = strSymbols
         ? castSlice(strSymbols, 1).join()
         : string.slice(1);
       return chr[methodName]() + trailing;
     };
   }
   /**
    * Creates a function like `_.camelCase`.
    *
    * @private
    * @param {Function} callback The function to combine each word.
    * @returns {Function} Returns the new compounder function.
    */
   function createCompounder(callback) {
     return function(string) {
       return arrayReduce(words(deburr(string).replace(reApos, )), callback, );
     };
   }
   /**
    * Creates a function that produces an instance of `Ctor` regardless of
    * whether it was invoked as part of a `new` expression or by `call` or `apply`.
    *
    * @private
    * @param {Function} Ctor The constructor to wrap.
    * @returns {Function} Returns the new wrapped function.
    */
   function createCtor(Ctor) {
     return function() {
       // Use a `switch` statement to work with class constructors. See
       // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
       // for more details.
       var args = arguments;
       switch (args.length) {
         case 0: return new Ctor;
         case 1: return new Ctor(args[0]);
         case 2: return new Ctor(args[0], args[1]);
         case 3: return new Ctor(args[0], args[1], args[2]);
         case 4: return new Ctor(args[0], args[1], args[2], args[3]);
         case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
         case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
         case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
       }
       var thisBinding = baseCreate(Ctor.prototype),
           result = Ctor.apply(thisBinding, args);
       // Mimic the constructor's `return` behavior.
       // See https://es5.github.io/#x13.2.2 for more details.
       return isObject(result) ? result : thisBinding;
     };
   }
   /**
    * Creates a function that wraps `func` to enable currying.
    *
    * @private
    * @param {Function} func The function to wrap.
    * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
    * @param {number} arity The arity of `func`.
    * @returns {Function} Returns the new wrapped function.
    */
   function createCurry(func, bitmask, arity) {
     var Ctor = createCtor(func);
     function wrapper() {
       var length = arguments.length,
           args = Array(length),
           index = length,
           placeholder = getHolder(wrapper);
       while (index--) {
         args[index] = arguments[index];
       }
       var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
         ? []
         : replaceHolders(args, placeholder);
       length -= holders.length;
       if (length < arity) {
         return createRecurry(
           func, bitmask, createHybrid, wrapper.placeholder, undefined,
           args, holders, undefined, undefined, arity - length);
       }
       var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
       return apply(fn, this, args);
     }
     return wrapper;
   }
   /**
    * Creates a `_.find` or `_.findLast` function.
    *
    * @private
    * @param {Function} findIndexFunc The function to find the collection index.
    * @returns {Function} Returns the new find function.
    */
   function createFind(findIndexFunc) {
     return function(collection, predicate, fromIndex) {
       var iterable = Object(collection);
       if (!isArrayLike(collection)) {
         var iteratee = getIteratee(predicate, 3);
         collection = keys(collection);
         predicate = function(key) { return iteratee(iterable[key], key, iterable); };
       }
       var index = findIndexFunc(collection, predicate, fromIndex);
       return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
     };
   }
   /**
    * Creates a `_.flow` or `_.flowRight` function.
    *
    * @private
    * @param {boolean} [fromRight] Specify iterating from right to left.
    * @returns {Function} Returns the new flow function.
    */
   function createFlow(fromRight) {
     return flatRest(function(funcs) {
       var length = funcs.length,
           index = length,
           prereq = LodashWrapper.prototype.thru;
       if (fromRight) {
         funcs.reverse();
       }
       while (index--) {
         var func = funcs[index];
         if (typeof func != 'function') {
           throw new TypeError(FUNC_ERROR_TEXT);
         }
         if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
           var wrapper = new LodashWrapper([], true);
         }
       }
       index = wrapper ? index : length;
       while (++index < length) {
         func = funcs[index];
         var funcName = getFuncName(func),
             data = funcName == 'wrapper' ? getData(func) : undefined;
         if (data && isLaziable(data[0]) &&
               data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
               !data[4].length && data[9] == 1
             ) {
           wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
         } else {
           wrapper = (func.length == 1 && isLaziable(func))
             ? wrapper[funcName]()
             : wrapper.thru(func);
         }
       }
       return function() {
         var args = arguments,
             value = args[0];
         if (wrapper && args.length == 1 && isArray(value)) {
           return wrapper.plant(value).value();
         }
         var index = 0,
             result = length ? funcs[index].apply(this, args) : value;
         while (++index < length) {
           result = funcs[index].call(this, result);
         }
         return result;
       };
     });
   }
   /**
    * Creates a function that wraps `func` to invoke it with optional `this`
    * binding of `thisArg`, partial application, and currying.
    *
    * @private
    * @param {Function|string} func The function or method name to wrap.
    * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
    * @param {*} [thisArg] The `this` binding of `func`.
    * @param {Array} [partials] The arguments to prepend to those provided to
    *  the new function.
    * @param {Array} [holders] The `partials` placeholder indexes.
    * @param {Array} [partialsRight] The arguments to append to those provided
    *  to the new function.
    * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
    * @param {Array} [argPos] The argument positions of the new function.
    * @param {number} [ary] The arity cap of `func`.
    * @param {number} [arity] The arity of `func`.
    * @returns {Function} Returns the new wrapped function.
    */
   function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
     var isAry = bitmask & WRAP_ARY_FLAG,
         isBind = bitmask & WRAP_BIND_FLAG,
         isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
         isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
         isFlip = bitmask & WRAP_FLIP_FLAG,
         Ctor = isBindKey ? undefined : createCtor(func);
     function wrapper() {
       var length = arguments.length,
           args = Array(length),
           index = length;
       while (index--) {
         args[index] = arguments[index];
       }
       if (isCurried) {
         var placeholder = getHolder(wrapper),
             holdersCount = countHolders(args, placeholder);
       }
       if (partials) {
         args = composeArgs(args, partials, holders, isCurried);
       }
       if (partialsRight) {
         args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
       }
       length -= holdersCount;
       if (isCurried && length < arity) {
         var newHolders = replaceHolders(args, placeholder);
         return createRecurry(
           func, bitmask, createHybrid, wrapper.placeholder, thisArg,
           args, newHolders, argPos, ary, arity - length
         );
       }
       var thisBinding = isBind ? thisArg : this,
           fn = isBindKey ? thisBinding[func] : func;
       length = args.length;
       if (argPos) {
         args = reorder(args, argPos);
       } else if (isFlip && length > 1) {
         args.reverse();
       }
       if (isAry && ary < length) {
         args.length = ary;
       }
       if (this && this !== root && this instanceof wrapper) {
         fn = Ctor || createCtor(fn);
       }
       return fn.apply(thisBinding, args);
     }
     return wrapper;
   }
   /**
    * Creates a function like `_.invertBy`.
    *
    * @private
    * @param {Function} setter The function to set accumulator values.
    * @param {Function} toIteratee The function to resolve iteratees.
    * @returns {Function} Returns the new inverter function.
    */
   function createInverter(setter, toIteratee) {
     return function(object, iteratee) {
       return baseInverter(object, setter, toIteratee(iteratee), {});
     };
   }
   /**
    * Creates a function that performs a mathematical operation on two values.
    *
    * @private
    * @param {Function} operator The function to perform the operation.
    * @param {number} [defaultValue] The value used for `undefined` arguments.
    * @returns {Function} Returns the new mathematical operation function.
    */
   function createMathOperation(operator, defaultValue) {
     return function(value, other) {
       var result;
       if (value === undefined && other === undefined) {
         return defaultValue;
       }
       if (value !== undefined) {
         result = value;
       }
       if (other !== undefined) {
         if (result === undefined) {
           return other;
         }
         if (typeof value == 'string' || typeof other == 'string') {
           value = baseToString(value);
           other = baseToString(other);
         } else {
           value = baseToNumber(value);
           other = baseToNumber(other);
         }
         result = operator(value, other);
       }
       return result;
     };
   }
   /**
    * Creates a function like `_.over`.
    *
    * @private
    * @param {Function} arrayFunc The function to iterate over iteratees.
    * @returns {Function} Returns the new over function.
    */
   function createOver(arrayFunc) {
     return flatRest(function(iteratees) {
       iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
       return baseRest(function(args) {
         var thisArg = this;
         return arrayFunc(iteratees, function(iteratee) {
           return apply(iteratee, thisArg, args);
         });
       });
     });
   }
   /**
    * Creates the padding for `string` based on `length`. The `chars` string
    * is truncated if the number of characters exceeds `length`.
    *
    * @private
    * @param {number} length The padding length.
    * @param {string} [chars=' '] The string used as padding.
    * @returns {string} Returns the padding for `string`.
    */
   function createPadding(length, chars) {
     chars = chars === undefined ? ' ' : baseToString(chars);
     var charsLength = chars.length;
     if (charsLength < 2) {
       return charsLength ? baseRepeat(chars, length) : chars;
     }
     var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
     return hasUnicode(chars)
       ? castSlice(stringToArray(result), 0, length).join()
       : result.slice(0, length);
   }
   /**
    * Creates a function that wraps `func` to invoke it with the `this` binding
    * of `thisArg` and `partials` prepended to the arguments it receives.
    *
    * @private
    * @param {Function} func The function to wrap.
    * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
    * @param {*} thisArg The `this` binding of `func`.
    * @param {Array} partials The arguments to prepend to those provided to
    *  the new function.
    * @returns {Function} Returns the new wrapped function.
    */
   function createPartial(func, bitmask, thisArg, partials) {
     var isBind = bitmask & WRAP_BIND_FLAG,
         Ctor = createCtor(func);
     function wrapper() {
       var argsIndex = -1,
           argsLength = arguments.length,
           leftIndex = -1,
           leftLength = partials.length,
           args = Array(leftLength + argsLength),
           fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
       while (++leftIndex < leftLength) {
         args[leftIndex] = partials[leftIndex];
       }
       while (argsLength--) {
         args[leftIndex++] = arguments[++argsIndex];
       }
       return apply(fn, isBind ? thisArg : this, args);
     }
     return wrapper;
   }
   /**
    * Creates a `_.range` or `_.rangeRight` function.
    *
    * @private
    * @param {boolean} [fromRight] Specify iterating from right to left.
    * @returns {Function} Returns the new range function.
    */
   function createRange(fromRight) {
     return function(start, end, step) {
       if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
         end = step = undefined;
       }
       // Ensure the sign of `-0` is preserved.
       start = toFinite(start);
       if (end === undefined) {
         end = start;
         start = 0;
       } else {
         end = toFinite(end);
       }
       step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
       return baseRange(start, end, step, fromRight);
     };
   }
   /**
    * Creates a function that performs a relational operation on two values.
    *
    * @private
    * @param {Function} operator The function to perform the operation.
    * @returns {Function} Returns the new relational operation function.
    */
   function createRelationalOperation(operator) {
     return function(value, other) {
       if (!(typeof value == 'string' && typeof other == 'string')) {
         value = toNumber(value);
         other = toNumber(other);
       }
       return operator(value, other);
     };
   }
   /**
    * Creates a function that wraps `func` to continue currying.
    *
    * @private
    * @param {Function} func The function to wrap.
    * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
    * @param {Function} wrapFunc The function to create the `func` wrapper.
    * @param {*} placeholder The placeholder value.
    * @param {*} [thisArg] The `this` binding of `func`.
    * @param {Array} [partials] The arguments to prepend to those provided to
    *  the new function.
    * @param {Array} [holders] The `partials` placeholder indexes.
    * @param {Array} [argPos] The argument positions of the new function.
    * @param {number} [ary] The arity cap of `func`.
    * @param {number} [arity] The arity of `func`.
    * @returns {Function} Returns the new wrapped function.
    */
   function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
     var isCurry = bitmask & WRAP_CURRY_FLAG,
         newHolders = isCurry ? holders : undefined,
         newHoldersRight = isCurry ? undefined : holders,
         newPartials = isCurry ? partials : undefined,
         newPartialsRight = isCurry ? undefined : partials;
     bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
     bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
     if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
       bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
     }
     var newData = [
       func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
       newHoldersRight, argPos, ary, arity
     ];
     var result = wrapFunc.apply(undefined, newData);
     if (isLaziable(func)) {
       setData(result, newData);
     }
     result.placeholder = placeholder;
     return setWrapToString(result, func, bitmask);
   }
   /**
    * Creates a function like `_.round`.
    *
    * @private
    * @param {string} methodName The name of the `Math` method to use when rounding.
    * @returns {Function} Returns the new round function.
    */
   function createRound(methodName) {
     var func = Math[methodName];
     return function(number, precision) {
       number = toNumber(number);
       precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
       if (precision && nativeIsFinite(number)) {
         // Shift with exponential notation to avoid floating-point issues.
         // See [MDN](https://mdn.io/round#Examples) for more details.
         var pair = (toString(number) + 'e').split('e'),
             value = func(pair[0] + 'e' + (+pair[1] + precision));
         pair = (toString(value) + 'e').split('e');
         return +(pair[0] + 'e' + (+pair[1] - precision));
       }
       return func(number);
     };
   }
   /**
    * Creates a set object of `values`.
    *
    * @private
    * @param {Array} values The values to add to the set.
    * @returns {Object} Returns the new set.
    */
   var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
     return new Set(values);
   };
   /**
    * Creates a `_.toPairs` or `_.toPairsIn` function.
    *
    * @private
    * @param {Function} keysFunc The function to get the keys of a given object.
    * @returns {Function} Returns the new pairs function.
    */
   function createToPairs(keysFunc) {
     return function(object) {
       var tag = getTag(object);
       if (tag == mapTag) {
         return mapToArray(object);
       }
       if (tag == setTag) {
         return setToPairs(object);
       }
       return baseToPairs(object, keysFunc(object));
     };
   }
   /**
    * Creates a function that either curries or invokes `func` with optional
    * `this` binding and partially applied arguments.
    *
    * @private
    * @param {Function|string} func The function or method name to wrap.
    * @param {number} bitmask The bitmask flags.
    *    1 - `_.bind`
    *    2 - `_.bindKey`
    *    4 - `_.curry` or `_.curryRight` of a bound function
    *    8 - `_.curry`
    *   16 - `_.curryRight`
    *   32 - `_.partial`
    *   64 - `_.partialRight`
    *  128 - `_.rearg`
    *  256 - `_.ary`
    *  512 - `_.flip`
    * @param {*} [thisArg] The `this` binding of `func`.
    * @param {Array} [partials] The arguments to be partially applied.
    * @param {Array} [holders] The `partials` placeholder indexes.
    * @param {Array} [argPos] The argument positions of the new function.
    * @param {number} [ary] The arity cap of `func`.
    * @param {number} [arity] The arity of `func`.
    * @returns {Function} Returns the new wrapped function.
    */
   function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
     var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
     if (!isBindKey && typeof func != 'function') {
       throw new TypeError(FUNC_ERROR_TEXT);
     }
     var length = partials ? partials.length : 0;
     if (!length) {
       bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
       partials = holders = undefined;
     }
     ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
     arity = arity === undefined ? arity : toInteger(arity);
     length -= holders ? holders.length : 0;
     if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
       var partialsRight = partials,
           holdersRight = holders;
       partials = holders = undefined;
     }
     var data = isBindKey ? undefined : getData(func);
     var newData = [
       func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
       argPos, ary, arity
     ];
     if (data) {
       mergeData(newData, data);
     }
     func = newData[0];
     bitmask = newData[1];
     thisArg = newData[2];
     partials = newData[3];
     holders = newData[4];
     arity = newData[9] = newData[9] === undefined
       ? (isBindKey ? 0 : func.length)
       : nativeMax(newData[9] - length, 0);
     if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
       bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
     }
     if (!bitmask || bitmask == WRAP_BIND_FLAG) {
       var result = createBind(func, bitmask, thisArg);
     } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
       result = createCurry(func, bitmask, arity);
     } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
       result = createPartial(func, bitmask, thisArg, partials);
     } else {
       result = createHybrid.apply(undefined, newData);
     }
     var setter = data ? baseSetData : setData;
     return setWrapToString(setter(result, newData), func, bitmask);
   }
   /**
    * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
    * of source objects to the destination object for all destination properties
    * that resolve to `undefined`.
    *
    * @private
    * @param {*} objValue The destination value.
    * @param {*} srcValue The source value.
    * @param {string} key The key of the property to assign.
    * @param {Object} object The parent object of `objValue`.
    * @returns {*} Returns the value to assign.
    */
   function customDefaultsAssignIn(objValue, srcValue, key, object) {
     if (objValue === undefined ||
         (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
       return srcValue;
     }
     return objValue;
   }
   /**
    * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
    * objects into destination objects that are passed thru.
    *
    * @private
    * @param {*} objValue The destination value.
    * @param {*} srcValue The source value.
    * @param {string} key The key of the property to merge.
    * @param {Object} object The parent object of `objValue`.
    * @param {Object} source The parent object of `srcValue`.
    * @param {Object} [stack] Tracks traversed source values and their merged
    *  counterparts.
    * @returns {*} Returns the value to assign.
    */
   function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
     if (isObject(objValue) && isObject(srcValue)) {
       // Recursively merge objects and arrays (susceptible to call stack limits).
       stack.set(srcValue, objValue);
       baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);
       stack['delete'](srcValue);
     }
     return objValue;
   }
   /**
    * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
    * objects.
    *
    * @private
    * @param {*} value The value to inspect.
    * @param {string} key The key of the property to inspect.
    * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
    */
   function customOmitClone(value) {
     return isPlainObject(value) ? undefined : value;
   }
   /**
    * A specialized version of `baseIsEqualDeep` for arrays with support for
    * partial deep comparisons.
    *
    * @private
    * @param {Array} array The array to compare.
    * @param {Array} other The other array to compare.
    * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
    * @param {Function} customizer The function to customize comparisons.
    * @param {Function} equalFunc The function to determine equivalents of values.
    * @param {Object} stack Tracks traversed `array` and `other` objects.
    * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
    */
   function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
     var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
         arrLength = array.length,
         othLength = other.length;
     if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
       return false;
     }
     // Assume cyclic values are equal.
     var stacked = stack.get(array);
     if (stacked && stack.get(other)) {
       return stacked == other;
     }
     var index = -1,
         result = true,
         seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
     stack.set(array, other);
     stack.set(other, array);
     // Ignore non-index properties.
     while (++index < arrLength) {
       var arrValue = array[index],
           othValue = other[index];
       if (customizer) {
         var compared = isPartial
           ? customizer(othValue, arrValue, index, other, array, stack)
           : customizer(arrValue, othValue, index, array, other, stack);
       }
       if (compared !== undefined) {
         if (compared) {
           continue;
         }
         result = false;
         break;
       }
       // Recursively compare arrays (susceptible to call stack limits).
       if (seen) {
         if (!arraySome(other, function(othValue, othIndex) {
               if (!cacheHas(seen, othIndex) &&
                   (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
                 return seen.push(othIndex);
               }
             })) {
           result = false;
           break;
         }
       } else if (!(
             arrValue === othValue ||
               equalFunc(arrValue, othValue, bitmask, customizer, stack)
           )) {
         result = false;
         break;
       }
     }
     stack['delete'](array);
     stack['delete'](other);
     return result;
   }
   /**
    * A specialized version of `baseIsEqualDeep` for comparing objects of
    * the same `toStringTag`.
    *
    * **Note:** This function only supports comparing values with tags of
    * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
    *
    * @private
    * @param {Object} object The object to compare.
    * @param {Object} other The other object to compare.
    * @param {string} tag The `toStringTag` of the objects to compare.
    * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
    * @param {Function} customizer The function to customize comparisons.
    * @param {Function} equalFunc The function to determine equivalents of values.
    * @param {Object} stack Tracks traversed `object` and `other` objects.
    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
    */
   function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
     switch (tag) {
       case dataViewTag:
         if ((object.byteLength != other.byteLength) ||
             (object.byteOffset != other.byteOffset)) {
           return false;
         }
         object = object.buffer;
         other = other.buffer;
       case arrayBufferTag:
         if ((object.byteLength != other.byteLength) ||
             !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
           return false;
         }
         return true;
       case boolTag:
       case dateTag:
       case numberTag:
         // Coerce booleans to `1` or `0` and dates to milliseconds.
         // Invalid dates are coerced to `NaN`.
         return eq(+object, +other);
       case errorTag:
         return object.name == other.name && object.message == other.message;
       case regexpTag:
       case stringTag:
         // Coerce regexes to strings and treat strings, primitives and objects,
         // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
         // for more details.
         return object == (other + );
       case mapTag:
         var convert = mapToArray;
       case setTag:
         var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
         convert || (convert = setToArray);
         if (object.size != other.size && !isPartial) {
           return false;
         }
         // Assume cyclic values are equal.
         var stacked = stack.get(object);
         if (stacked) {
           return stacked == other;
         }
         bitmask |= COMPARE_UNORDERED_FLAG;
         // Recursively compare objects (susceptible to call stack limits).
         stack.set(object, other);
         var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
         stack['delete'](object);
         return result;
       case symbolTag:
         if (symbolValueOf) {
           return symbolValueOf.call(object) == symbolValueOf.call(other);
         }
     }
     return false;
   }
   /**
    * A specialized version of `baseIsEqualDeep` for objects with support for
    * partial deep comparisons.
    *
    * @private
    * @param {Object} object The object to compare.
    * @param {Object} other The other object to compare.
    * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
    * @param {Function} customizer The function to customize comparisons.
    * @param {Function} equalFunc The function to determine equivalents of values.
    * @param {Object} stack Tracks traversed `object` and `other` objects.
    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
    */
   function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
     var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
         objProps = getAllKeys(object),
         objLength = objProps.length,
         othProps = getAllKeys(other),
         othLength = othProps.length;
     if (objLength != othLength && !isPartial) {
       return false;
     }
     var index = objLength;
     while (index--) {
       var key = objProps[index];
       if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
         return false;
       }
     }
     // Assume cyclic values are equal.
     var stacked = stack.get(object);
     if (stacked && stack.get(other)) {
       return stacked == other;
     }
     var result = true;
     stack.set(object, other);
     stack.set(other, object);
     var skipCtor = isPartial;
     while (++index < objLength) {
       key = objProps[index];
       var objValue = object[key],
           othValue = other[key];
       if (customizer) {
         var compared = isPartial
           ? customizer(othValue, objValue, key, other, object, stack)
           : customizer(objValue, othValue, key, object, other, stack);
       }
       // Recursively compare objects (susceptible to call stack limits).
       if (!(compared === undefined
             ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
             : compared
           )) {
         result = false;
         break;
       }
       skipCtor || (skipCtor = key == 'constructor');
     }
     if (result && !skipCtor) {
       var objCtor = object.constructor,
           othCtor = other.constructor;
       // Non `Object` object instances with different constructors are not equal.
       if (objCtor != othCtor &&
           ('constructor' in object && 'constructor' in other) &&
           !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
             typeof othCtor == 'function' && othCtor instanceof othCtor)) {
         result = false;
       }
     }
     stack['delete'](object);
     stack['delete'](other);
     return result;
   }
   /**
    * A specialized version of `baseRest` which flattens the rest array.
    *
    * @private
    * @param {Function} func The function to apply a rest parameter to.
    * @returns {Function} Returns the new function.
    */
   function flatRest(func) {
     return setToString(overRest(func, undefined, flatten), func + );
   }
   /**
    * Creates an array of own enumerable property names and symbols of `object`.
    *
    * @private
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of property names and symbols.
    */
   function getAllKeys(object) {
     return baseGetAllKeys(object, keys, getSymbols);
   }
   /**
    * Creates an array of own and inherited enumerable property names and
    * symbols of `object`.
    *
    * @private
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of property names and symbols.
    */
   function getAllKeysIn(object) {
     return baseGetAllKeys(object, keysIn, getSymbolsIn);
   }
   /**
    * Gets metadata for `func`.
    *
    * @private
    * @param {Function} func The function to query.
    * @returns {*} Returns the metadata for `func`.
    */
   var getData = !metaMap ? noop : function(func) {
     return metaMap.get(func);
   };
   /**
    * Gets the name of `func`.
    *
    * @private
    * @param {Function} func The function to query.
    * @returns {string} Returns the function name.
    */
   function getFuncName(func) {
     var result = (func.name + ),
         array = realNames[result],
         length = hasOwnProperty.call(realNames, result) ? array.length : 0;
     while (length--) {
       var data = array[length],
           otherFunc = data.func;
       if (otherFunc == null || otherFunc == func) {
         return data.name;
       }
     }
     return result;
   }
   /**
    * Gets the argument placeholder value for `func`.
    *
    * @private
    * @param {Function} func The function to inspect.
    * @returns {*} Returns the placeholder value.
    */
   function getHolder(func) {
     var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
     return object.placeholder;
   }
   /**
    * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
    * this function returns the custom method, otherwise it returns `baseIteratee`.
    * If arguments are provided, the chosen function is invoked with them and
    * its result is returned.
    *
    * @private
    * @param {*} [value] The value to convert to an iteratee.
    * @param {number} [arity] The arity of the created iteratee.
    * @returns {Function} Returns the chosen function or its result.
    */
   function getIteratee() {
     var result = lodash.iteratee || iteratee;
     result = result === iteratee ? baseIteratee : result;
     return arguments.length ? result(arguments[0], arguments[1]) : result;
   }
   /**
    * Gets the data for `map`.
    *
    * @private
    * @param {Object} map The map to query.
    * @param {string} key The reference key.
    * @returns {*} Returns the map data.
    */
   function getMapData(map, key) {
     var data = map.__data__;
     return isKeyable(key)
       ? data[typeof key == 'string' ? 'string' : 'hash']
       : data.map;
   }
   /**
    * Gets the property names, values, and compare flags of `object`.
    *
    * @private
    * @param {Object} object The object to query.
    * @returns {Array} Returns the match data of `object`.
    */
   function getMatchData(object) {
     var result = keys(object),
         length = result.length;
     while (length--) {
       var key = result[length],
           value = object[key];
       result[length] = [key, value, isStrictComparable(value)];
     }
     return result;
   }
   /**
    * Gets the native function at `key` of `object`.
    *
    * @private
    * @param {Object} object The object to query.
    * @param {string} key The key of the method to get.
    * @returns {*} Returns the function if it's native, else `undefined`.
    */
   function getNative(object, key) {
     var value = getValue(object, key);
     return baseIsNative(value) ? value : undefined;
   }
   /**
    * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
    *
    * @private
    * @param {*} value The value to query.
    * @returns {string} Returns the raw `toStringTag`.
    */
   function getRawTag(value) {
     var isOwn = hasOwnProperty.call(value, symToStringTag),
         tag = value[symToStringTag];
     try {
       value[symToStringTag] = undefined;
       var unmasked = true;
     } catch (e) {}
     var result = nativeObjectToString.call(value);
     if (unmasked) {
       if (isOwn) {
         value[symToStringTag] = tag;
       } else {
         delete value[symToStringTag];
       }
     }
     return result;
   }
   /**
    * Creates an array of the own enumerable symbols of `object`.
    *
    * @private
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of symbols.
    */
   var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
     if (object == null) {
       return [];
     }
     object = Object(object);
     return arrayFilter(nativeGetSymbols(object), function(symbol) {
       return propertyIsEnumerable.call(object, symbol);
     });
   };
   /**
    * Creates an array of the own and inherited enumerable symbols of `object`.
    *
    * @private
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of symbols.
    */
   var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
     var result = [];
     while (object) {
       arrayPush(result, getSymbols(object));
       object = getPrototype(object);
     }
     return result;
   };
   /**
    * Gets the `toStringTag` of `value`.
    *
    * @private
    * @param {*} value The value to query.
    * @returns {string} Returns the `toStringTag`.
    */
   var getTag = baseGetTag;
   // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
   if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
       (Map && getTag(new Map) != mapTag) ||
       (Promise && getTag(Promise.resolve()) != promiseTag) ||
       (Set && getTag(new Set) != setTag) ||
       (WeakMap && getTag(new WeakMap) != weakMapTag)) {
     getTag = function(value) {
       var result = baseGetTag(value),
           Ctor = result == objectTag ? value.constructor : undefined,
           ctorString = Ctor ? toSource(Ctor) : ;
       if (ctorString) {
         switch (ctorString) {
           case dataViewCtorString: return dataViewTag;
           case mapCtorString: return mapTag;
           case promiseCtorString: return promiseTag;
           case setCtorString: return setTag;
           case weakMapCtorString: return weakMapTag;
         }
       }
       return result;
     };
   }
   /**
    * Gets the view, applying any `transforms` to the `start` and `end` positions.
    *
    * @private
    * @param {number} start The start of the view.
    * @param {number} end The end of the view.
    * @param {Array} transforms The transformations to apply to the view.
    * @returns {Object} Returns an object containing the `start` and `end`
    *  positions of the view.
    */
   function getView(start, end, transforms) {
     var index = -1,
         length = transforms.length;
     while (++index < length) {
       var data = transforms[index],
           size = data.size;
       switch (data.type) {
         case 'drop':      start += size; break;
         case 'dropRight': end -= size; break;
         case 'take':      end = nativeMin(end, start + size); break;
         case 'takeRight': start = nativeMax(start, end - size); break;
       }
     }
     return { 'start': start, 'end': end };
   }
   /**
    * Extracts wrapper details from the `source` body comment.
    *
    * @private
    * @param {string} source The source to inspect.
    * @returns {Array} Returns the wrapper details.
    */
   function getWrapDetails(source) {
     var match = source.match(reWrapDetails);
     return match ? match[1].split(reSplitDetails) : [];
   }
   /**
    * Checks if `path` exists on `object`.
    *
    * @private
    * @param {Object} object The object to query.
    * @param {Array|string} path The path to check.
    * @param {Function} hasFunc The function to check properties.
    * @returns {boolean} Returns `true` if `path` exists, else `false`.
    */
   function hasPath(object, path, hasFunc) {
     path = castPath(path, object);
     var index = -1,
         length = path.length,
         result = false;
     while (++index < length) {
       var key = toKey(path[index]);
       if (!(result = object != null && hasFunc(object, key))) {
         break;
       }
       object = object[key];
     }
     if (result || ++index != length) {
       return result;
     }
     length = object == null ? 0 : object.length;
     return !!length && isLength(length) && isIndex(key, length) &&
       (isArray(object) || isArguments(object));
   }
   /**
    * Initializes an array clone.
    *
    * @private
    * @param {Array} array The array to clone.
    * @returns {Array} Returns the initialized clone.
    */
   function initCloneArray(array) {
     var length = array.length,
         result = new array.constructor(length);
     // Add properties assigned by `RegExp#exec`.
     if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
       result.index = array.index;
       result.input = array.input;
     }
     return result;
   }
   /**
    * Initializes an object clone.
    *
    * @private
    * @param {Object} object The object to clone.
    * @returns {Object} Returns the initialized clone.
    */
   function initCloneObject(object) {
     return (typeof object.constructor == 'function' && !isPrototype(object))
       ? baseCreate(getPrototype(object))
       : {};
   }
   /**
    * Initializes an object clone based on its `toStringTag`.
    *
    * **Note:** This function only supports cloning values with tags of
    * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.
    *
    * @private
    * @param {Object} object The object to clone.
    * @param {string} tag The `toStringTag` of the object to clone.
    * @param {boolean} [isDeep] Specify a deep clone.
    * @returns {Object} Returns the initialized clone.
    */
   function initCloneByTag(object, tag, isDeep) {
     var Ctor = object.constructor;
     switch (tag) {
       case arrayBufferTag:
         return cloneArrayBuffer(object);
       case boolTag:
       case dateTag:
         return new Ctor(+object);
       case dataViewTag:
         return cloneDataView(object, isDeep);
       case float32Tag: case float64Tag:
       case int8Tag: case int16Tag: case int32Tag:
       case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
         return cloneTypedArray(object, isDeep);
       case mapTag:
         return new Ctor;
       case numberTag:
       case stringTag:
         return new Ctor(object);
       case regexpTag:
         return cloneRegExp(object);
       case setTag:
         return new Ctor;
       case symbolTag:
         return cloneSymbol(object);
     }
   }
   /**
    * Inserts wrapper `details` in a comment at the top of the `source` body.
    *
    * @private
    * @param {string} source The source to modify.
    * @returns {Array} details The details to insert.
    * @returns {string} Returns the modified source.
    */
   function insertWrapDetails(source, details) {
     var length = details.length;
     if (!length) {
       return source;
     }
     var lastIndex = length - 1;
     details[lastIndex] = (length > 1 ? '& ' : ) + details[lastIndex];
     details = details.join(length > 2 ? ', ' : ' ');
     return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
   }
   /**
    * Checks if `value` is a flattenable `arguments` object or array.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
    */
   function isFlattenable(value) {
     return isArray(value) || isArguments(value) ||
       !!(spreadableSymbol && value && value[spreadableSymbol]);
   }
   /**
    * Checks if `value` is a valid array-like index.
    *
    * @private
    * @param {*} value The value to check.
    * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
    * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
    */
   function isIndex(value, length) {
     var type = typeof value;
     length = length == null ? MAX_SAFE_INTEGER : length;
     return !!length &&
       (type == 'number' ||
         (type != 'symbol' && reIsUint.test(value))) &&
           (value > -1 && value % 1 == 0 && value < length);
   }
   /**
    * Checks if the given arguments are from an iteratee call.
    *
    * @private
    * @param {*} value The potential iteratee value argument.
    * @param {*} index The potential iteratee index or key argument.
    * @param {*} object The potential iteratee object argument.
    * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
    *  else `false`.
    */
   function isIterateeCall(value, index, object) {
     if (!isObject(object)) {
       return false;
     }
     var type = typeof index;
     if (type == 'number'
           ? (isArrayLike(object) && isIndex(index, object.length))
           : (type == 'string' && index in object)
         ) {
       return eq(object[index], value);
     }
     return false;
   }
   /**
    * Checks if `value` is a property name and not a property path.
    *
    * @private
    * @param {*} value The value to check.
    * @param {Object} [object] The object to query keys on.
    * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
    */
   function isKey(value, object) {
     if (isArray(value)) {
       return false;
     }
     var type = typeof value;
     if (type == 'number' || type == 'symbol' || type == 'boolean' ||
         value == null || isSymbol(value)) {
       return true;
     }
     return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
       (object != null && value in Object(object));
   }
   /**
    * Checks if `value` is suitable for use as unique object key.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
    */
   function isKeyable(value) {
     var type = typeof value;
     return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
       ? (value !== '__proto__')
       : (value === null);
   }
   /**
    * Checks if `func` has a lazy counterpart.
    *
    * @private
    * @param {Function} func The function to check.
    * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
    *  else `false`.
    */
   function isLaziable(func) {
     var funcName = getFuncName(func),
         other = lodash[funcName];
     if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
       return false;
     }
     if (func === other) {
       return true;
     }
     var data = getData(other);
     return !!data && func === data[0];
   }
   /**
    * Checks if `func` has its source masked.
    *
    * @private
    * @param {Function} func The function to check.
    * @returns {boolean} Returns `true` if `func` is masked, else `false`.
    */
   function isMasked(func) {
     return !!maskSrcKey && (maskSrcKey in func);
   }
   /**
    * Checks if `func` is capable of being masked.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
    */
   var isMaskable = coreJsData ? isFunction : stubFalse;
   /**
    * Checks if `value` is likely a prototype object.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
    */
   function isPrototype(value) {
     var Ctor = value && value.constructor,
         proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
     return value === proto;
   }
   /**
    * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
    *
    * @private
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` if suitable for strict
    *  equality comparisons, else `false`.
    */
   function isStrictComparable(value) {
     return value === value && !isObject(value);
   }
   /**
    * A specialized version of `matchesProperty` for source values suitable
    * for strict equality comparisons, i.e. `===`.
    *
    * @private
    * @param {string} key The key of the property to get.
    * @param {*} srcValue The value to match.
    * @returns {Function} Returns the new spec function.
    */
   function matchesStrictComparable(key, srcValue) {
     return function(object) {
       if (object == null) {
         return false;
       }
       return object[key] === srcValue &&
         (srcValue !== undefined || (key in Object(object)));
     };
   }
   /**
    * A specialized version of `_.memoize` which clears the memoized function's
    * cache when it exceeds `MAX_MEMOIZE_SIZE`.
    *
    * @private
    * @param {Function} func The function to have its output memoized.
    * @returns {Function} Returns the new memoized function.
    */
   function memoizeCapped(func) {
     var result = memoize(func, function(key) {
       if (cache.size === MAX_MEMOIZE_SIZE) {
         cache.clear();
       }
       return key;
     });
     var cache = result.cache;
     return result;
   }
   /**
    * Merges the function metadata of `source` into `data`.
    *
    * Merging metadata reduces the number of wrappers used to invoke a function.
    * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
    * may be applied regardless of execution order. Methods like `_.ary` and
    * `_.rearg` modify function arguments, making the order in which they are
    * executed important, preventing the merging of metadata. However, we make
    * an exception for a safe combined case where curried functions have `_.ary`
    * and or `_.rearg` applied.
    *
    * @private
    * @param {Array} data The destination metadata.
    * @param {Array} source The source metadata.
    * @returns {Array} Returns `data`.
    */
   function mergeData(data, source) {
     var bitmask = data[1],
         srcBitmask = source[1],
         newBitmask = bitmask | srcBitmask,
         isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
     var isCombo =
       ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
       ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
       ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
     // Exit early if metadata can't be merged.
     if (!(isCommon || isCombo)) {
       return data;
     }
     // Use source `thisArg` if available.
     if (srcBitmask & WRAP_BIND_FLAG) {
       data[2] = source[2];
       // Set when currying a bound function.
       newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
     }
     // Compose partial arguments.
     var value = source[3];
     if (value) {
       var partials = data[3];
       data[3] = partials ? composeArgs(partials, value, source[4]) : value;
       data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
     }
     // Compose partial right arguments.
     value = source[5];
     if (value) {
       partials = data[5];
       data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
       data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
     }
     // Use source `argPos` if available.
     value = source[7];
     if (value) {
       data[7] = value;
     }
     // Use source `ary` if it's smaller.
     if (srcBitmask & WRAP_ARY_FLAG) {
       data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
     }
     // Use source `arity` if one is not provided.
     if (data[9] == null) {
       data[9] = source[9];
     }
     // Use source `func` and merge bitmasks.
     data[0] = source[0];
     data[1] = newBitmask;
     return data;
   }
   /**
    * This function is like
    * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
    * except that it includes inherited enumerable properties.
    *
    * @private
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of property names.
    */
   function nativeKeysIn(object) {
     var result = [];
     if (object != null) {
       for (var key in Object(object)) {
         result.push(key);
       }
     }
     return result;
   }
   /**
    * Converts `value` to a string using `Object.prototype.toString`.
    *
    * @private
    * @param {*} value The value to convert.
    * @returns {string} Returns the converted string.
    */
   function objectToString(value) {
     return nativeObjectToString.call(value);
   }
   /**
    * A specialized version of `baseRest` which transforms the rest array.
    *
    * @private
    * @param {Function} func The function to apply a rest parameter to.
    * @param {number} [start=func.length-1] The start position of the rest parameter.
    * @param {Function} transform The rest array transform.
    * @returns {Function} Returns the new function.
    */
   function overRest(func, start, transform) {
     start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
     return function() {
       var args = arguments,
           index = -1,
           length = nativeMax(args.length - start, 0),
           array = Array(length);
       while (++index < length) {
         array[index] = args[start + index];
       }
       index = -1;
       var otherArgs = Array(start + 1);
       while (++index < start) {
         otherArgs[index] = args[index];
       }
       otherArgs[start] = transform(array);
       return apply(func, this, otherArgs);
     };
   }
   /**
    * Gets the parent value at `path` of `object`.
    *
    * @private
    * @param {Object} object The object to query.
    * @param {Array} path The path to get the parent value of.
    * @returns {*} Returns the parent value.
    */
   function parent(object, path) {
     return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
   }
   /**
    * Reorder `array` according to the specified indexes where the element at
    * the first index is assigned as the first element, the element at
    * the second index is assigned as the second element, and so on.
    *
    * @private
    * @param {Array} array The array to reorder.
    * @param {Array} indexes The arranged array indexes.
    * @returns {Array} Returns `array`.
    */
   function reorder(array, indexes) {
     var arrLength = array.length,
         length = nativeMin(indexes.length, arrLength),
         oldArray = copyArray(array);
     while (length--) {
       var index = indexes[length];
       array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
     }
     return array;
   }
   /**
    * Gets the value at `key`, unless `key` is "__proto__" or "constructor".
    *
    * @private
    * @param {Object} object The object to query.
    * @param {string} key The key of the property to get.
    * @returns {*} Returns the property value.
    */
   function safeGet(object, key) {
     if (key === 'constructor' && typeof object[key] === 'function') {
       return;
     }
     if (key == '__proto__') {
       return;
     }
     return object[key];
   }
   /**
    * Sets metadata for `func`.
    *
    * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
    * period of time, it will trip its breaker and transition to an identity
    * function to avoid garbage collection pauses in V8. See
    * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
    * for more details.
    *
    * @private
    * @param {Function} func The function to associate metadata with.
    * @param {*} data The metadata.
    * @returns {Function} Returns `func`.
    */
   var setData = shortOut(baseSetData);
   /**
    * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
    *
    * @private
    * @param {Function} func The function to delay.
    * @param {number} wait The number of milliseconds to delay invocation.
    * @returns {number|Object} Returns the timer id or timeout object.
    */
   var setTimeout = ctxSetTimeout || function(func, wait) {
     return root.setTimeout(func, wait);
   };
   /**
    * Sets the `toString` method of `func` to return `string`.
    *
    * @private
    * @param {Function} func The function to modify.
    * @param {Function} string The `toString` result.
    * @returns {Function} Returns `func`.
    */
   var setToString = shortOut(baseSetToString);
   /**
    * Sets the `toString` method of `wrapper` to mimic the source of `reference`
    * with wrapper details in a comment at the top of the source body.
    *
    * @private
    * @param {Function} wrapper The function to modify.
    * @param {Function} reference The reference function.
    * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
    * @returns {Function} Returns `wrapper`.
    */
   function setWrapToString(wrapper, reference, bitmask) {
     var source = (reference + );
     return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
   }
   /**
    * Creates a function that'll short out and invoke `identity` instead
    * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
    * milliseconds.
    *
    * @private
    * @param {Function} func The function to restrict.
    * @returns {Function} Returns the new shortable function.
    */
   function shortOut(func) {
     var count = 0,
         lastCalled = 0;
     return function() {
       var stamp = nativeNow(),
           remaining = HOT_SPAN - (stamp - lastCalled);
       lastCalled = stamp;
       if (remaining > 0) {
         if (++count >= HOT_COUNT) {
           return arguments[0];
         }
       } else {
         count = 0;
       }
       return func.apply(undefined, arguments);
     };
   }
   /**
    * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
    *
    * @private
    * @param {Array} array The array to shuffle.
    * @param {number} [size=array.length] The size of `array`.
    * @returns {Array} Returns `array`.
    */
   function shuffleSelf(array, size) {
     var index = -1,
         length = array.length,
         lastIndex = length - 1;
     size = size === undefined ? length : size;
     while (++index < size) {
       var rand = baseRandom(index, lastIndex),
           value = array[rand];
       array[rand] = array[index];
       array[index] = value;
     }
     array.length = size;
     return array;
   }
   /**
    * Converts `string` to a property path array.
    *
    * @private
    * @param {string} string The string to convert.
    * @returns {Array} Returns the property path array.
    */
   var stringToPath = memoizeCapped(function(string) {
     var result = [];
     if (string.charCodeAt(0) === 46 /* . */) {
       result.push();
     }
     string.replace(rePropName, function(match, number, quote, subString) {
       result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));
     });
     return result;
   });
   /**
    * Converts `value` to a string key if it's not a string or symbol.
    *
    * @private
    * @param {*} value The value to inspect.
    * @returns {string|symbol} Returns the key.
    */
   function toKey(value) {
     if (typeof value == 'string' || isSymbol(value)) {
       return value;
     }
     var result = (value + );
     return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
   }
   /**
    * Converts `func` to its source code.
    *
    * @private
    * @param {Function} func The function to convert.
    * @returns {string} Returns the source code.
    */
   function toSource(func) {
     if (func != null) {
       try {
         return funcToString.call(func);
       } catch (e) {}
       try {
         return (func + );
       } catch (e) {}
     }
     return ;
   }
   /**
    * Updates wrapper `details` based on `bitmask` flags.
    *
    * @private
    * @returns {Array} details The details to modify.
    * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
    * @returns {Array} Returns `details`.
    */
   function updateWrapDetails(details, bitmask) {
     arrayEach(wrapFlags, function(pair) {
       var value = '_.' + pair[0];
       if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
         details.push(value);
       }
     });
     return details.sort();
   }
   /**
    * Creates a clone of `wrapper`.
    *
    * @private
    * @param {Object} wrapper The wrapper to clone.
    * @returns {Object} Returns the cloned wrapper.
    */
   function wrapperClone(wrapper) {
     if (wrapper instanceof LazyWrapper) {
       return wrapper.clone();
     }
     var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
     result.__actions__ = copyArray(wrapper.__actions__);
     result.__index__  = wrapper.__index__;
     result.__values__ = wrapper.__values__;
     return result;
   }
   /*------------------------------------------------------------------------*/
   /**
    * Creates an array of elements split into groups the length of `size`.
    * If `array` can't be split evenly, the final chunk will be the remaining
    * elements.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The array to process.
    * @param {number} [size=1] The length of each chunk
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {Array} Returns the new array of chunks.
    * @example
    *
    * _.chunk(['a', 'b', 'c', 'd'], 2);
    * // => [['a', 'b'], ['c', 'd']]
    *
    * _.chunk(['a', 'b', 'c', 'd'], 3);
    * // => [['a', 'b', 'c'], ['d']]
    */
   function chunk(array, size, guard) {
     if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
       size = 1;
     } else {
       size = nativeMax(toInteger(size), 0);
     }
     var length = array == null ? 0 : array.length;
     if (!length || size < 1) {
       return [];
     }
     var index = 0,
         resIndex = 0,
         result = Array(nativeCeil(length / size));
     while (index < length) {
       result[resIndex++] = baseSlice(array, index, (index += size));
     }
     return result;
   }
   /**
    * Creates an array with all falsey values removed. The values `false`, `null`,
    * `0`, `""`, `undefined`, and `NaN` are falsey.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The array to compact.
    * @returns {Array} Returns the new array of filtered values.
    * @example
    *
    * _.compact([0, 1, false, 2, , 3]);
    * // => [1, 2, 3]
    */
   function compact(array) {
     var index = -1,
         length = array == null ? 0 : array.length,
         resIndex = 0,
         result = [];
     while (++index < length) {
       var value = array[index];
       if (value) {
         result[resIndex++] = value;
       }
     }
     return result;
   }
   /**
    * Creates a new array concatenating `array` with any additional arrays
    * and/or values.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to concatenate.
    * @param {...*} [values] The values to concatenate.
    * @returns {Array} Returns the new concatenated array.
    * @example
    *
    * var array = [1];
    * var other = _.concat(array, 2, [3], 4);
    *
    * console.log(other);
    * // => [1, 2, 3, [4]]
    *
    * console.log(array);
    * // => [1]
    */
   function concat() {
     var length = arguments.length;
     if (!length) {
       return [];
     }
     var args = Array(length - 1),
         array = arguments[0],
         index = length;
     while (index--) {
       args[index - 1] = arguments[index];
     }
     return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
   }
   /**
    * Creates an array of `array` values not included in the other given arrays
    * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
    * for equality comparisons. The order and references of result values are
    * determined by the first array.
    *
    * **Note:** Unlike `_.pullAll`, this method returns a new array.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {...Array} [values] The values to exclude.
    * @returns {Array} Returns the new array of filtered values.
    * @see _.without, _.xor
    * @example
    *
    * _.difference([2, 1], [2, 3]);
    * // => [1]
    */
   var difference = baseRest(function(array, values) {
     return isArrayLikeObject(array)
       ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
       : [];
   });
   /**
    * This method is like `_.difference` except that it accepts `iteratee` which
    * is invoked for each element of `array` and `values` to generate the criterion
    * by which they're compared. The order and references of result values are
    * determined by the first array. The iteratee is invoked with one argument:
    * (value).
    *
    * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {...Array} [values] The values to exclude.
    * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
    * @returns {Array} Returns the new array of filtered values.
    * @example
    *
    * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
    * // => [1.2]
    *
    * // The `_.property` iteratee shorthand.
    * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
    * // => [{ 'x': 2 }]
    */
   var differenceBy = baseRest(function(array, values) {
     var iteratee = last(values);
     if (isArrayLikeObject(iteratee)) {
       iteratee = undefined;
     }
     return isArrayLikeObject(array)
       ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
       : [];
   });
   /**
    * This method is like `_.difference` except that it accepts `comparator`
    * which is invoked to compare elements of `array` to `values`. The order and
    * references of result values are determined by the first array. The comparator
    * is invoked with two arguments: (arrVal, othVal).
    *
    * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {...Array} [values] The values to exclude.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns the new array of filtered values.
    * @example
    *
    * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
    *
    * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
    * // => [{ 'x': 2, 'y': 1 }]
    */
   var differenceWith = baseRest(function(array, values) {
     var comparator = last(values);
     if (isArrayLikeObject(comparator)) {
       comparator = undefined;
     }
     return isArrayLikeObject(array)
       ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
       : [];
   });
   /**
    * Creates a slice of `array` with `n` elements dropped from the beginning.
    *
    * @static
    * @memberOf _
    * @since 0.5.0
    * @category Array
    * @param {Array} array The array to query.
    * @param {number} [n=1] The number of elements to drop.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {Array} Returns the slice of `array`.
    * @example
    *
    * _.drop([1, 2, 3]);
    * // => [2, 3]
    *
    * _.drop([1, 2, 3], 2);
    * // => [3]
    *
    * _.drop([1, 2, 3], 5);
    * // => []
    *
    * _.drop([1, 2, 3], 0);
    * // => [1, 2, 3]
    */
   function drop(array, n, guard) {
     var length = array == null ? 0 : array.length;
     if (!length) {
       return [];
     }
     n = (guard || n === undefined) ? 1 : toInteger(n);
     return baseSlice(array, n < 0 ? 0 : n, length);
   }
   /**
    * Creates a slice of `array` with `n` elements dropped from the end.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The array to query.
    * @param {number} [n=1] The number of elements to drop.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {Array} Returns the slice of `array`.
    * @example
    *
    * _.dropRight([1, 2, 3]);
    * // => [1, 2]
    *
    * _.dropRight([1, 2, 3], 2);
    * // => [1]
    *
    * _.dropRight([1, 2, 3], 5);
    * // => []
    *
    * _.dropRight([1, 2, 3], 0);
    * // => [1, 2, 3]
    */
   function dropRight(array, n, guard) {
     var length = array == null ? 0 : array.length;
     if (!length) {
       return [];
     }
     n = (guard || n === undefined) ? 1 : toInteger(n);
     n = length - n;
     return baseSlice(array, 0, n < 0 ? 0 : n);
   }
   /**
    * Creates a slice of `array` excluding elements dropped from the end.
    * Elements are dropped until `predicate` returns falsey. The predicate is
    * invoked with three arguments: (value, index, array).
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The array to query.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the slice of `array`.
    * @example
    *
    * var users = [
    *   { 'user': 'barney',  'active': true },
    *   { 'user': 'fred',    'active': false },
    *   { 'user': 'pebbles', 'active': false }
    * ];
    *
    * _.dropRightWhile(users, function(o) { return !o.active; });
    * // => objects for ['barney']
    *
    * // The `_.matches` iteratee shorthand.
    * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
    * // => objects for ['barney', 'fred']
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.dropRightWhile(users, ['active', false]);
    * // => objects for ['barney']
    *
    * // The `_.property` iteratee shorthand.
    * _.dropRightWhile(users, 'active');
    * // => objects for ['barney', 'fred', 'pebbles']
    */
   function dropRightWhile(array, predicate) {
     return (array && array.length)
       ? baseWhile(array, getIteratee(predicate, 3), true, true)
       : [];
   }
   /**
    * Creates a slice of `array` excluding elements dropped from the beginning.
    * Elements are dropped until `predicate` returns falsey. The predicate is
    * invoked with three arguments: (value, index, array).
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The array to query.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the slice of `array`.
    * @example
    *
    * var users = [
    *   { 'user': 'barney',  'active': false },
    *   { 'user': 'fred',    'active': false },
    *   { 'user': 'pebbles', 'active': true }
    * ];
    *
    * _.dropWhile(users, function(o) { return !o.active; });
    * // => objects for ['pebbles']
    *
    * // The `_.matches` iteratee shorthand.
    * _.dropWhile(users, { 'user': 'barney', 'active': false });
    * // => objects for ['fred', 'pebbles']
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.dropWhile(users, ['active', false]);
    * // => objects for ['pebbles']
    *
    * // The `_.property` iteratee shorthand.
    * _.dropWhile(users, 'active');
    * // => objects for ['barney', 'fred', 'pebbles']
    */
   function dropWhile(array, predicate) {
     return (array && array.length)
       ? baseWhile(array, getIteratee(predicate, 3), true)
       : [];
   }
   /**
    * Fills elements of `array` with `value` from `start` up to, but not
    * including, `end`.
    *
    * **Note:** This method mutates `array`.
    *
    * @static
    * @memberOf _
    * @since 3.2.0
    * @category Array
    * @param {Array} array The array to fill.
    * @param {*} value The value to fill `array` with.
    * @param {number} [start=0] The start position.
    * @param {number} [end=array.length] The end position.
    * @returns {Array} Returns `array`.
    * @example
    *
    * var array = [1, 2, 3];
    *
    * _.fill(array, 'a');
    * console.log(array);
    * // => ['a', 'a', 'a']
    *
    * _.fill(Array(3), 2);
    * // => [2, 2, 2]
    *
    * _.fill([4, 6, 8, 10], '*', 1, 3);
    * // => [4, '*', '*', 10]
    */
   function fill(array, value, start, end) {
     var length = array == null ? 0 : array.length;
     if (!length) {
       return [];
     }
     if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
       start = 0;
       end = length;
     }
     return baseFill(array, value, start, end);
   }
   /**
    * This method is like `_.find` except that it returns the index of the first
    * element `predicate` returns truthy for instead of the element itself.
    *
    * @static
    * @memberOf _
    * @since 1.1.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @param {number} [fromIndex=0] The index to search from.
    * @returns {number} Returns the index of the found element, else `-1`.
    * @example
    *
    * var users = [
    *   { 'user': 'barney',  'active': false },
    *   { 'user': 'fred',    'active': false },
    *   { 'user': 'pebbles', 'active': true }
    * ];
    *
    * _.findIndex(users, function(o) { return o.user == 'barney'; });
    * // => 0
    *
    * // The `_.matches` iteratee shorthand.
    * _.findIndex(users, { 'user': 'fred', 'active': false });
    * // => 1
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.findIndex(users, ['active', false]);
    * // => 0
    *
    * // The `_.property` iteratee shorthand.
    * _.findIndex(users, 'active');
    * // => 2
    */
   function findIndex(array, predicate, fromIndex) {
     var length = array == null ? 0 : array.length;
     if (!length) {
       return -1;
     }
     var index = fromIndex == null ? 0 : toInteger(fromIndex);
     if (index < 0) {
       index = nativeMax(length + index, 0);
     }
     return baseFindIndex(array, getIteratee(predicate, 3), index);
   }
   /**
    * This method is like `_.findIndex` except that it iterates over elements
    * of `collection` from right to left.
    *
    * @static
    * @memberOf _
    * @since 2.0.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @param {number} [fromIndex=array.length-1] The index to search from.
    * @returns {number} Returns the index of the found element, else `-1`.
    * @example
    *
    * var users = [
    *   { 'user': 'barney',  'active': true },
    *   { 'user': 'fred',    'active': false },
    *   { 'user': 'pebbles', 'active': false }
    * ];
    *
    * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
    * // => 2
    *
    * // The `_.matches` iteratee shorthand.
    * _.findLastIndex(users, { 'user': 'barney', 'active': true });
    * // => 0
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.findLastIndex(users, ['active', false]);
    * // => 2
    *
    * // The `_.property` iteratee shorthand.
    * _.findLastIndex(users, 'active');
    * // => 0
    */
   function findLastIndex(array, predicate, fromIndex) {
     var length = array == null ? 0 : array.length;
     if (!length) {
       return -1;
     }
     var index = length - 1;
     if (fromIndex !== undefined) {
       index = toInteger(fromIndex);
       index = fromIndex < 0
         ? nativeMax(length + index, 0)
         : nativeMin(index, length - 1);
     }
     return baseFindIndex(array, getIteratee(predicate, 3), index, true);
   }
   /**
    * Flattens `array` a single level deep.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The array to flatten.
    * @returns {Array} Returns the new flattened array.
    * @example
    *
    * _.flatten([1, [2, [3, [4]], 5]]);
    * // => [1, 2, [3, [4]], 5]
    */
   function flatten(array) {
     var length = array == null ? 0 : array.length;
     return length ? baseFlatten(array, 1) : [];
   }
   /**
    * Recursively flattens `array`.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The array to flatten.
    * @returns {Array} Returns the new flattened array.
    * @example
    *
    * _.flattenDeep([1, [2, [3, [4]], 5]]);
    * // => [1, 2, 3, 4, 5]
    */
   function flattenDeep(array) {
     var length = array == null ? 0 : array.length;
     return length ? baseFlatten(array, INFINITY) : [];
   }
   /**
    * Recursively flatten `array` up to `depth` times.
    *
    * @static
    * @memberOf _
    * @since 4.4.0
    * @category Array
    * @param {Array} array The array to flatten.
    * @param {number} [depth=1] The maximum recursion depth.
    * @returns {Array} Returns the new flattened array.
    * @example
    *
    * var array = [1, [2, [3, [4]], 5]];
    *
    * _.flattenDepth(array, 1);
    * // => [1, 2, [3, [4]], 5]
    *
    * _.flattenDepth(array, 2);
    * // => [1, 2, 3, [4], 5]
    */
   function flattenDepth(array, depth) {
     var length = array == null ? 0 : array.length;
     if (!length) {
       return [];
     }
     depth = depth === undefined ? 1 : toInteger(depth);
     return baseFlatten(array, depth);
   }
   /**
    * The inverse of `_.toPairs`; this method returns an object composed
    * from key-value `pairs`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} pairs The key-value pairs.
    * @returns {Object} Returns the new object.
    * @example
    *
    * _.fromPairs([['a', 1], ['b', 2]]);
    * // => { 'a': 1, 'b': 2 }
    */
   function fromPairs(pairs) {
     var index = -1,
         length = pairs == null ? 0 : pairs.length,
         result = {};
     while (++index < length) {
       var pair = pairs[index];
       result[pair[0]] = pair[1];
     }
     return result;
   }
   /**
    * Gets the first element of `array`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @alias first
    * @category Array
    * @param {Array} array The array to query.
    * @returns {*} Returns the first element of `array`.
    * @example
    *
    * _.head([1, 2, 3]);
    * // => 1
    *
    * _.head([]);
    * // => undefined
    */
   function head(array) {
     return (array && array.length) ? array[0] : undefined;
   }
   /**
    * Gets the index at which the first occurrence of `value` is found in `array`
    * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
    * for equality comparisons. If `fromIndex` is negative, it's used as the
    * offset from the end of `array`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {*} value The value to search for.
    * @param {number} [fromIndex=0] The index to search from.
    * @returns {number} Returns the index of the matched value, else `-1`.
    * @example
    *
    * _.indexOf([1, 2, 1, 2], 2);
    * // => 1
    *
    * // Search from the `fromIndex`.
    * _.indexOf([1, 2, 1, 2], 2, 2);
    * // => 3
    */
   function indexOf(array, value, fromIndex) {
     var length = array == null ? 0 : array.length;
     if (!length) {
       return -1;
     }
     var index = fromIndex == null ? 0 : toInteger(fromIndex);
     if (index < 0) {
       index = nativeMax(length + index, 0);
     }
     return baseIndexOf(array, value, index);
   }
   /**
    * Gets all but the last element of `array`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The array to query.
    * @returns {Array} Returns the slice of `array`.
    * @example
    *
    * _.initial([1, 2, 3]);
    * // => [1, 2]
    */
   function initial(array) {
     var length = array == null ? 0 : array.length;
     return length ? baseSlice(array, 0, -1) : [];
   }
   /**
    * Creates an array of unique values that are included in all given arrays
    * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
    * for equality comparisons. The order and references of result values are
    * determined by the first array.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {...Array} [arrays] The arrays to inspect.
    * @returns {Array} Returns the new array of intersecting values.
    * @example
    *
    * _.intersection([2, 1], [2, 3]);
    * // => [2]
    */
   var intersection = baseRest(function(arrays) {
     var mapped = arrayMap(arrays, castArrayLikeObject);
     return (mapped.length && mapped[0] === arrays[0])
       ? baseIntersection(mapped)
       : [];
   });
   /**
    * This method is like `_.intersection` except that it accepts `iteratee`
    * which is invoked for each element of each `arrays` to generate the criterion
    * by which they're compared. The order and references of result values are
    * determined by the first array. The iteratee is invoked with one argument:
    * (value).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {...Array} [arrays] The arrays to inspect.
    * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
    * @returns {Array} Returns the new array of intersecting values.
    * @example
    *
    * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
    * // => [2.1]
    *
    * // The `_.property` iteratee shorthand.
    * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
    * // => [{ 'x': 1 }]
    */
   var intersectionBy = baseRest(function(arrays) {
     var iteratee = last(arrays),
         mapped = arrayMap(arrays, castArrayLikeObject);
     if (iteratee === last(mapped)) {
       iteratee = undefined;
     } else {
       mapped.pop();
     }
     return (mapped.length && mapped[0] === arrays[0])
       ? baseIntersection(mapped, getIteratee(iteratee, 2))
       : [];
   });
   /**
    * This method is like `_.intersection` except that it accepts `comparator`
    * which is invoked to compare elements of `arrays`. The order and references
    * of result values are determined by the first array. The comparator is
    * invoked with two arguments: (arrVal, othVal).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {...Array} [arrays] The arrays to inspect.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns the new array of intersecting values.
    * @example
    *
    * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
    * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
    *
    * _.intersectionWith(objects, others, _.isEqual);
    * // => [{ 'x': 1, 'y': 2 }]
    */
   var intersectionWith = baseRest(function(arrays) {
     var comparator = last(arrays),
         mapped = arrayMap(arrays, castArrayLikeObject);
     comparator = typeof comparator == 'function' ? comparator : undefined;
     if (comparator) {
       mapped.pop();
     }
     return (mapped.length && mapped[0] === arrays[0])
       ? baseIntersection(mapped, undefined, comparator)
       : [];
   });
   /**
    * Converts all elements in `array` into a string separated by `separator`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to convert.
    * @param {string} [separator=','] The element separator.
    * @returns {string} Returns the joined string.
    * @example
    *
    * _.join(['a', 'b', 'c'], '~');
    * // => 'a~b~c'
    */
   function join(array, separator) {
     return array == null ?  : nativeJoin.call(array, separator);
   }
   /**
    * Gets the last element of `array`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The array to query.
    * @returns {*} Returns the last element of `array`.
    * @example
    *
    * _.last([1, 2, 3]);
    * // => 3
    */
   function last(array) {
     var length = array == null ? 0 : array.length;
     return length ? array[length - 1] : undefined;
   }
   /**
    * This method is like `_.indexOf` except that it iterates over elements of
    * `array` from right to left.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {*} value The value to search for.
    * @param {number} [fromIndex=array.length-1] The index to search from.
    * @returns {number} Returns the index of the matched value, else `-1`.
    * @example
    *
    * _.lastIndexOf([1, 2, 1, 2], 2);
    * // => 3
    *
    * // Search from the `fromIndex`.
    * _.lastIndexOf([1, 2, 1, 2], 2, 2);
    * // => 1
    */
   function lastIndexOf(array, value, fromIndex) {
     var length = array == null ? 0 : array.length;
     if (!length) {
       return -1;
     }
     var index = length;
     if (fromIndex !== undefined) {
       index = toInteger(fromIndex);
       index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
     }
     return value === value
       ? strictLastIndexOf(array, value, index)
       : baseFindIndex(array, baseIsNaN, index, true);
   }
   /**
    * Gets the element at index `n` of `array`. If `n` is negative, the nth
    * element from the end is returned.
    *
    * @static
    * @memberOf _
    * @since 4.11.0
    * @category Array
    * @param {Array} array The array to query.
    * @param {number} [n=0] The index of the element to return.
    * @returns {*} Returns the nth element of `array`.
    * @example
    *
    * var array = ['a', 'b', 'c', 'd'];
    *
    * _.nth(array, 1);
    * // => 'b'
    *
    * _.nth(array, -2);
    * // => 'c';
    */
   function nth(array, n) {
     return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
   }
   /**
    * Removes all given values from `array` using
    * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
    * for equality comparisons.
    *
    * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
    * to remove elements from an array by predicate.
    *
    * @static
    * @memberOf _
    * @since 2.0.0
    * @category Array
    * @param {Array} array The array to modify.
    * @param {...*} [values] The values to remove.
    * @returns {Array} Returns `array`.
    * @example
    *
    * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
    *
    * _.pull(array, 'a', 'c');
    * console.log(array);
    * // => ['b', 'b']
    */
   var pull = baseRest(pullAll);
   /**
    * This method is like `_.pull` except that it accepts an array of values to remove.
    *
    * **Note:** Unlike `_.difference`, this method mutates `array`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to modify.
    * @param {Array} values The values to remove.
    * @returns {Array} Returns `array`.
    * @example
    *
    * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
    *
    * _.pullAll(array, ['a', 'c']);
    * console.log(array);
    * // => ['b', 'b']
    */
   function pullAll(array, values) {
     return (array && array.length && values && values.length)
       ? basePullAll(array, values)
       : array;
   }
   /**
    * This method is like `_.pullAll` except that it accepts `iteratee` which is
    * invoked for each element of `array` and `values` to generate the criterion
    * by which they're compared. The iteratee is invoked with one argument: (value).
    *
    * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to modify.
    * @param {Array} values The values to remove.
    * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
    * @returns {Array} Returns `array`.
    * @example
    *
    * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
    *
    * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
    * console.log(array);
    * // => [{ 'x': 2 }]
    */
   function pullAllBy(array, values, iteratee) {
     return (array && array.length && values && values.length)
       ? basePullAll(array, values, getIteratee(iteratee, 2))
       : array;
   }
   /**
    * This method is like `_.pullAll` except that it accepts `comparator` which
    * is invoked to compare elements of `array` to `values`. The comparator is
    * invoked with two arguments: (arrVal, othVal).
    *
    * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
    *
    * @static
    * @memberOf _
    * @since 4.6.0
    * @category Array
    * @param {Array} array The array to modify.
    * @param {Array} values The values to remove.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns `array`.
    * @example
    *
    * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
    *
    * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
    * console.log(array);
    * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
    */
   function pullAllWith(array, values, comparator) {
     return (array && array.length && values && values.length)
       ? basePullAll(array, values, undefined, comparator)
       : array;
   }
   /**
    * Removes elements from `array` corresponding to `indexes` and returns an
    * array of removed elements.
    *
    * **Note:** Unlike `_.at`, this method mutates `array`.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The array to modify.
    * @param {...(number|number[])} [indexes] The indexes of elements to remove.
    * @returns {Array} Returns the new array of removed elements.
    * @example
    *
    * var array = ['a', 'b', 'c', 'd'];
    * var pulled = _.pullAt(array, [1, 3]);
    *
    * console.log(array);
    * // => ['a', 'c']
    *
    * console.log(pulled);
    * // => ['b', 'd']
    */
   var pullAt = flatRest(function(array, indexes) {
     var length = array == null ? 0 : array.length,
         result = baseAt(array, indexes);
     basePullAt(array, arrayMap(indexes, function(index) {
       return isIndex(index, length) ? +index : index;
     }).sort(compareAscending));
     return result;
   });
   /**
    * Removes all elements from `array` that `predicate` returns truthy for
    * and returns an array of the removed elements. The predicate is invoked
    * with three arguments: (value, index, array).
    *
    * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
    * to pull elements from an array by value.
    *
    * @static
    * @memberOf _
    * @since 2.0.0
    * @category Array
    * @param {Array} array The array to modify.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the new array of removed elements.
    * @example
    *
    * var array = [1, 2, 3, 4];
    * var evens = _.remove(array, function(n) {
    *   return n % 2 == 0;
    * });
    *
    * console.log(array);
    * // => [1, 3]
    *
    * console.log(evens);
    * // => [2, 4]
    */
   function remove(array, predicate) {
     var result = [];
     if (!(array && array.length)) {
       return result;
     }
     var index = -1,
         indexes = [],
         length = array.length;
     predicate = getIteratee(predicate, 3);
     while (++index < length) {
       var value = array[index];
       if (predicate(value, index, array)) {
         result.push(value);
         indexes.push(index);
       }
     }
     basePullAt(array, indexes);
     return result;
   }
   /**
    * Reverses `array` so that the first element becomes the last, the second
    * element becomes the second to last, and so on.
    *
    * **Note:** This method mutates `array` and is based on
    * [`Array#reverse`](https://mdn.io/Array/reverse).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to modify.
    * @returns {Array} Returns `array`.
    * @example
    *
    * var array = [1, 2, 3];
    *
    * _.reverse(array);
    * // => [3, 2, 1]
    *
    * console.log(array);
    * // => [3, 2, 1]
    */
   function reverse(array) {
     return array == null ? array : nativeReverse.call(array);
   }
   /**
    * Creates a slice of `array` from `start` up to, but not including, `end`.
    *
    * **Note:** This method is used instead of
    * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
    * returned.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The array to slice.
    * @param {number} [start=0] The start position.
    * @param {number} [end=array.length] The end position.
    * @returns {Array} Returns the slice of `array`.
    */
   function slice(array, start, end) {
     var length = array == null ? 0 : array.length;
     if (!length) {
       return [];
     }
     if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
       start = 0;
       end = length;
     }
     else {
       start = start == null ? 0 : toInteger(start);
       end = end === undefined ? length : toInteger(end);
     }
     return baseSlice(array, start, end);
   }
   /**
    * Uses a binary search to determine the lowest index at which `value`
    * should be inserted into `array` in order to maintain its sort order.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The sorted array to inspect.
    * @param {*} value The value to evaluate.
    * @returns {number} Returns the index at which `value` should be inserted
    *  into `array`.
    * @example
    *
    * _.sortedIndex([30, 50], 40);
    * // => 1
    */
   function sortedIndex(array, value) {
     return baseSortedIndex(array, value);
   }
   /**
    * This method is like `_.sortedIndex` except that it accepts `iteratee`
    * which is invoked for `value` and each element of `array` to compute their
    * sort ranking. The iteratee is invoked with one argument: (value).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The sorted array to inspect.
    * @param {*} value The value to evaluate.
    * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
    * @returns {number} Returns the index at which `value` should be inserted
    *  into `array`.
    * @example
    *
    * var objects = [{ 'x': 4 }, { 'x': 5 }];
    *
    * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
    * // => 0
    *
    * // The `_.property` iteratee shorthand.
    * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
    * // => 0
    */
   function sortedIndexBy(array, value, iteratee) {
     return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
   }
   /**
    * This method is like `_.indexOf` except that it performs a binary
    * search on a sorted `array`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {*} value The value to search for.
    * @returns {number} Returns the index of the matched value, else `-1`.
    * @example
    *
    * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
    * // => 1
    */
   function sortedIndexOf(array, value) {
     var length = array == null ? 0 : array.length;
     if (length) {
       var index = baseSortedIndex(array, value);
       if (index < length && eq(array[index], value)) {
         return index;
       }
     }
     return -1;
   }
   /**
    * This method is like `_.sortedIndex` except that it returns the highest
    * index at which `value` should be inserted into `array` in order to
    * maintain its sort order.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The sorted array to inspect.
    * @param {*} value The value to evaluate.
    * @returns {number} Returns the index at which `value` should be inserted
    *  into `array`.
    * @example
    *
    * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
    * // => 4
    */
   function sortedLastIndex(array, value) {
     return baseSortedIndex(array, value, true);
   }
   /**
    * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
    * which is invoked for `value` and each element of `array` to compute their
    * sort ranking. The iteratee is invoked with one argument: (value).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The sorted array to inspect.
    * @param {*} value The value to evaluate.
    * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
    * @returns {number} Returns the index at which `value` should be inserted
    *  into `array`.
    * @example
    *
    * var objects = [{ 'x': 4 }, { 'x': 5 }];
    *
    * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
    * // => 1
    *
    * // The `_.property` iteratee shorthand.
    * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
    * // => 1
    */
   function sortedLastIndexBy(array, value, iteratee) {
     return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
   }
   /**
    * This method is like `_.lastIndexOf` except that it performs a binary
    * search on a sorted `array`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {*} value The value to search for.
    * @returns {number} Returns the index of the matched value, else `-1`.
    * @example
    *
    * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
    * // => 3
    */
   function sortedLastIndexOf(array, value) {
     var length = array == null ? 0 : array.length;
     if (length) {
       var index = baseSortedIndex(array, value, true) - 1;
       if (eq(array[index], value)) {
         return index;
       }
     }
     return -1;
   }
   /**
    * This method is like `_.uniq` except that it's designed and optimized
    * for sorted arrays.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @returns {Array} Returns the new duplicate free array.
    * @example
    *
    * _.sortedUniq([1, 1, 2]);
    * // => [1, 2]
    */
   function sortedUniq(array) {
     return (array && array.length)
       ? baseSortedUniq(array)
       : [];
   }
   /**
    * This method is like `_.uniqBy` except that it's designed and optimized
    * for sorted arrays.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {Function} [iteratee] The iteratee invoked per element.
    * @returns {Array} Returns the new duplicate free array.
    * @example
    *
    * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
    * // => [1.1, 2.3]
    */
   function sortedUniqBy(array, iteratee) {
     return (array && array.length)
       ? baseSortedUniq(array, getIteratee(iteratee, 2))
       : [];
   }
   /**
    * Gets all but the first element of `array`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to query.
    * @returns {Array} Returns the slice of `array`.
    * @example
    *
    * _.tail([1, 2, 3]);
    * // => [2, 3]
    */
   function tail(array) {
     var length = array == null ? 0 : array.length;
     return length ? baseSlice(array, 1, length) : [];
   }
   /**
    * Creates a slice of `array` with `n` elements taken from the beginning.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The array to query.
    * @param {number} [n=1] The number of elements to take.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {Array} Returns the slice of `array`.
    * @example
    *
    * _.take([1, 2, 3]);
    * // => [1]
    *
    * _.take([1, 2, 3], 2);
    * // => [1, 2]
    *
    * _.take([1, 2, 3], 5);
    * // => [1, 2, 3]
    *
    * _.take([1, 2, 3], 0);
    * // => []
    */
   function take(array, n, guard) {
     if (!(array && array.length)) {
       return [];
     }
     n = (guard || n === undefined) ? 1 : toInteger(n);
     return baseSlice(array, 0, n < 0 ? 0 : n);
   }
   /**
    * Creates a slice of `array` with `n` elements taken from the end.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The array to query.
    * @param {number} [n=1] The number of elements to take.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {Array} Returns the slice of `array`.
    * @example
    *
    * _.takeRight([1, 2, 3]);
    * // => [3]
    *
    * _.takeRight([1, 2, 3], 2);
    * // => [2, 3]
    *
    * _.takeRight([1, 2, 3], 5);
    * // => [1, 2, 3]
    *
    * _.takeRight([1, 2, 3], 0);
    * // => []
    */
   function takeRight(array, n, guard) {
     var length = array == null ? 0 : array.length;
     if (!length) {
       return [];
     }
     n = (guard || n === undefined) ? 1 : toInteger(n);
     n = length - n;
     return baseSlice(array, n < 0 ? 0 : n, length);
   }
   /**
    * Creates a slice of `array` with elements taken from the end. Elements are
    * taken until `predicate` returns falsey. The predicate is invoked with
    * three arguments: (value, index, array).
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The array to query.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the slice of `array`.
    * @example
    *
    * var users = [
    *   { 'user': 'barney',  'active': true },
    *   { 'user': 'fred',    'active': false },
    *   { 'user': 'pebbles', 'active': false }
    * ];
    *
    * _.takeRightWhile(users, function(o) { return !o.active; });
    * // => objects for ['fred', 'pebbles']
    *
    * // The `_.matches` iteratee shorthand.
    * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
    * // => objects for ['pebbles']
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.takeRightWhile(users, ['active', false]);
    * // => objects for ['fred', 'pebbles']
    *
    * // The `_.property` iteratee shorthand.
    * _.takeRightWhile(users, 'active');
    * // => []
    */
   function takeRightWhile(array, predicate) {
     return (array && array.length)
       ? baseWhile(array, getIteratee(predicate, 3), false, true)
       : [];
   }
   /**
    * Creates a slice of `array` with elements taken from the beginning. Elements
    * are taken until `predicate` returns falsey. The predicate is invoked with
    * three arguments: (value, index, array).
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Array
    * @param {Array} array The array to query.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the slice of `array`.
    * @example
    *
    * var users = [
    *   { 'user': 'barney',  'active': false },
    *   { 'user': 'fred',    'active': false },
    *   { 'user': 'pebbles', 'active': true }
    * ];
    *
    * _.takeWhile(users, function(o) { return !o.active; });
    * // => objects for ['barney', 'fred']
    *
    * // The `_.matches` iteratee shorthand.
    * _.takeWhile(users, { 'user': 'barney', 'active': false });
    * // => objects for ['barney']
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.takeWhile(users, ['active', false]);
    * // => objects for ['barney', 'fred']
    *
    * // The `_.property` iteratee shorthand.
    * _.takeWhile(users, 'active');
    * // => []
    */
   function takeWhile(array, predicate) {
     return (array && array.length)
       ? baseWhile(array, getIteratee(predicate, 3))
       : [];
   }
   /**
    * Creates an array of unique values, in order, from all given arrays using
    * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
    * for equality comparisons.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {...Array} [arrays] The arrays to inspect.
    * @returns {Array} Returns the new array of combined values.
    * @example
    *
    * _.union([2], [1, 2]);
    * // => [2, 1]
    */
   var union = baseRest(function(arrays) {
     return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
   });
   /**
    * This method is like `_.union` except that it accepts `iteratee` which is
    * invoked for each element of each `arrays` to generate the criterion by
    * which uniqueness is computed. Result values are chosen from the first
    * array in which the value occurs. The iteratee is invoked with one argument:
    * (value).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {...Array} [arrays] The arrays to inspect.
    * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
    * @returns {Array} Returns the new array of combined values.
    * @example
    *
    * _.unionBy([2.1], [1.2, 2.3], Math.floor);
    * // => [2.1, 1.2]
    *
    * // The `_.property` iteratee shorthand.
    * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
    * // => [{ 'x': 1 }, { 'x': 2 }]
    */
   var unionBy = baseRest(function(arrays) {
     var iteratee = last(arrays);
     if (isArrayLikeObject(iteratee)) {
       iteratee = undefined;
     }
     return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
   });
   /**
    * This method is like `_.union` except that it accepts `comparator` which
    * is invoked to compare elements of `arrays`. Result values are chosen from
    * the first array in which the value occurs. The comparator is invoked
    * with two arguments: (arrVal, othVal).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {...Array} [arrays] The arrays to inspect.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns the new array of combined values.
    * @example
    *
    * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
    * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
    *
    * _.unionWith(objects, others, _.isEqual);
    * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
    */
   var unionWith = baseRest(function(arrays) {
     var comparator = last(arrays);
     comparator = typeof comparator == 'function' ? comparator : undefined;
     return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
   });
   /**
    * Creates a duplicate-free version of an array, using
    * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
    * for equality comparisons, in which only the first occurrence of each element
    * is kept. The order of result values is determined by the order they occur
    * in the array.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @returns {Array} Returns the new duplicate free array.
    * @example
    *
    * _.uniq([2, 1, 2]);
    * // => [2, 1]
    */
   function uniq(array) {
     return (array && array.length) ? baseUniq(array) : [];
   }
   /**
    * This method is like `_.uniq` except that it accepts `iteratee` which is
    * invoked for each element in `array` to generate the criterion by which
    * uniqueness is computed. The order of result values is determined by the
    * order they occur in the array. The iteratee is invoked with one argument:
    * (value).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
    * @returns {Array} Returns the new duplicate free array.
    * @example
    *
    * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
    * // => [2.1, 1.2]
    *
    * // The `_.property` iteratee shorthand.
    * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
    * // => [{ 'x': 1 }, { 'x': 2 }]
    */
   function uniqBy(array, iteratee) {
     return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
   }
   /**
    * This method is like `_.uniq` except that it accepts `comparator` which
    * is invoked to compare elements of `array`. The order of result values is
    * determined by the order they occur in the array.The comparator is invoked
    * with two arguments: (arrVal, othVal).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns the new duplicate free array.
    * @example
    *
    * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
    *
    * _.uniqWith(objects, _.isEqual);
    * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
    */
   function uniqWith(array, comparator) {
     comparator = typeof comparator == 'function' ? comparator : undefined;
     return (array && array.length) ? baseUniq(array, undefined, comparator) : [];
   }
   /**
    * This method is like `_.zip` except that it accepts an array of grouped
    * elements and creates an array regrouping the elements to their pre-zip
    * configuration.
    *
    * @static
    * @memberOf _
    * @since 1.2.0
    * @category Array
    * @param {Array} array The array of grouped elements to process.
    * @returns {Array} Returns the new array of regrouped elements.
    * @example
    *
    * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
    * // => [['a', 1, true], ['b', 2, false]]
    *
    * _.unzip(zipped);
    * // => [['a', 'b'], [1, 2], [true, false]]
    */
   function unzip(array) {
     if (!(array && array.length)) {
       return [];
     }
     var length = 0;
     array = arrayFilter(array, function(group) {
       if (isArrayLikeObject(group)) {
         length = nativeMax(group.length, length);
         return true;
       }
     });
     return baseTimes(length, function(index) {
       return arrayMap(array, baseProperty(index));
     });
   }
   /**
    * This method is like `_.unzip` except that it accepts `iteratee` to specify
    * how regrouped values should be combined. The iteratee is invoked with the
    * elements of each group: (...group).
    *
    * @static
    * @memberOf _
    * @since 3.8.0
    * @category Array
    * @param {Array} array The array of grouped elements to process.
    * @param {Function} [iteratee=_.identity] The function to combine
    *  regrouped values.
    * @returns {Array} Returns the new array of regrouped elements.
    * @example
    *
    * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
    * // => [[1, 10, 100], [2, 20, 200]]
    *
    * _.unzipWith(zipped, _.add);
    * // => [3, 30, 300]
    */
   function unzipWith(array, iteratee) {
     if (!(array && array.length)) {
       return [];
     }
     var result = unzip(array);
     if (iteratee == null) {
       return result;
     }
     return arrayMap(result, function(group) {
       return apply(iteratee, undefined, group);
     });
   }
   /**
    * Creates an array excluding all given values using
    * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
    * for equality comparisons.
    *
    * **Note:** Unlike `_.pull`, this method returns a new array.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {Array} array The array to inspect.
    * @param {...*} [values] The values to exclude.
    * @returns {Array} Returns the new array of filtered values.
    * @see _.difference, _.xor
    * @example
    *
    * _.without([2, 1, 2, 3], 1, 2);
    * // => [3]
    */
   var without = baseRest(function(array, values) {
     return isArrayLikeObject(array)
       ? baseDifference(array, values)
       : [];
   });
   /**
    * Creates an array of unique values that is the
    * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
    * of the given arrays. The order of result values is determined by the order
    * they occur in the arrays.
    *
    * @static
    * @memberOf _
    * @since 2.4.0
    * @category Array
    * @param {...Array} [arrays] The arrays to inspect.
    * @returns {Array} Returns the new array of filtered values.
    * @see _.difference, _.without
    * @example
    *
    * _.xor([2, 1], [2, 3]);
    * // => [1, 3]
    */
   var xor = baseRest(function(arrays) {
     return baseXor(arrayFilter(arrays, isArrayLikeObject));
   });
   /**
    * This method is like `_.xor` except that it accepts `iteratee` which is
    * invoked for each element of each `arrays` to generate the criterion by
    * which by which they're compared. The order of result values is determined
    * by the order they occur in the arrays. The iteratee is invoked with one
    * argument: (value).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {...Array} [arrays] The arrays to inspect.
    * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
    * @returns {Array} Returns the new array of filtered values.
    * @example
    *
    * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
    * // => [1.2, 3.4]
    *
    * // The `_.property` iteratee shorthand.
    * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
    * // => [{ 'x': 2 }]
    */
   var xorBy = baseRest(function(arrays) {
     var iteratee = last(arrays);
     if (isArrayLikeObject(iteratee)) {
       iteratee = undefined;
     }
     return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
   });
   /**
    * This method is like `_.xor` except that it accepts `comparator` which is
    * invoked to compare elements of `arrays`. The order of result values is
    * determined by the order they occur in the arrays. The comparator is invoked
    * with two arguments: (arrVal, othVal).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Array
    * @param {...Array} [arrays] The arrays to inspect.
    * @param {Function} [comparator] The comparator invoked per element.
    * @returns {Array} Returns the new array of filtered values.
    * @example
    *
    * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
    * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
    *
    * _.xorWith(objects, others, _.isEqual);
    * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
    */
   var xorWith = baseRest(function(arrays) {
     var comparator = last(arrays);
     comparator = typeof comparator == 'function' ? comparator : undefined;
     return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
   });
   /**
    * Creates an array of grouped elements, the first of which contains the
    * first elements of the given arrays, the second of which contains the
    * second elements of the given arrays, and so on.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Array
    * @param {...Array} [arrays] The arrays to process.
    * @returns {Array} Returns the new array of grouped elements.
    * @example
    *
    * _.zip(['a', 'b'], [1, 2], [true, false]);
    * // => [['a', 1, true], ['b', 2, false]]
    */
   var zip = baseRest(unzip);
   /**
    * This method is like `_.fromPairs` except that it accepts two arrays,
    * one of property identifiers and one of corresponding values.
    *
    * @static
    * @memberOf _
    * @since 0.4.0
    * @category Array
    * @param {Array} [props=[]] The property identifiers.
    * @param {Array} [values=[]] The property values.
    * @returns {Object} Returns the new object.
    * @example
    *
    * _.zipObject(['a', 'b'], [1, 2]);
    * // => { 'a': 1, 'b': 2 }
    */
   function zipObject(props, values) {
     return baseZipObject(props || [], values || [], assignValue);
   }
   /**
    * This method is like `_.zipObject` except that it supports property paths.
    *
    * @static
    * @memberOf _
    * @since 4.1.0
    * @category Array
    * @param {Array} [props=[]] The property identifiers.
    * @param {Array} [values=[]] The property values.
    * @returns {Object} Returns the new object.
    * @example
    *
    * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
    * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
    */
   function zipObjectDeep(props, values) {
     return baseZipObject(props || [], values || [], baseSet);
   }
   /**
    * This method is like `_.zip` except that it accepts `iteratee` to specify
    * how grouped values should be combined. The iteratee is invoked with the
    * elements of each group: (...group).
    *
    * @static
    * @memberOf _
    * @since 3.8.0
    * @category Array
    * @param {...Array} [arrays] The arrays to process.
    * @param {Function} [iteratee=_.identity] The function to combine
    *  grouped values.
    * @returns {Array} Returns the new array of grouped elements.
    * @example
    *
    * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
    *   return a + b + c;
    * });
    * // => [111, 222]
    */
   var zipWith = baseRest(function(arrays) {
     var length = arrays.length,
         iteratee = length > 1 ? arrays[length - 1] : undefined;
     iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
     return unzipWith(arrays, iteratee);
   });
   /*------------------------------------------------------------------------*/
   /**
    * Creates a `lodash` wrapper instance that wraps `value` with explicit method
    * chain sequences enabled. The result of such sequences must be unwrapped
    * with `_#value`.
    *
    * @static
    * @memberOf _
    * @since 1.3.0
    * @category Seq
    * @param {*} value The value to wrap.
    * @returns {Object} Returns the new `lodash` wrapper instance.
    * @example
    *
    * var users = [
    *   { 'user': 'barney',  'age': 36 },
    *   { 'user': 'fred',    'age': 40 },
    *   { 'user': 'pebbles', 'age': 1 }
    * ];
    *
    * var youngest = _
    *   .chain(users)
    *   .sortBy('age')
    *   .map(function(o) {
    *     return o.user + ' is ' + o.age;
    *   })
    *   .head()
    *   .value();
    * // => 'pebbles is 1'
    */
   function chain(value) {
     var result = lodash(value);
     result.__chain__ = true;
     return result;
   }
   /**
    * This method invokes `interceptor` and returns `value`. The interceptor
    * is invoked with one argument; (value). The purpose of this method is to
    * "tap into" a method chain sequence in order to modify intermediate results.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Seq
    * @param {*} value The value to provide to `interceptor`.
    * @param {Function} interceptor The function to invoke.
    * @returns {*} Returns `value`.
    * @example
    *
    * _([1, 2, 3])
    *  .tap(function(array) {
    *    // Mutate input array.
    *    array.pop();
    *  })
    *  .reverse()
    *  .value();
    * // => [2, 1]
    */
   function tap(value, interceptor) {
     interceptor(value);
     return value;
   }
   /**
    * This method is like `_.tap` except that it returns the result of `interceptor`.
    * The purpose of this method is to "pass thru" values replacing intermediate
    * results in a method chain sequence.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Seq
    * @param {*} value The value to provide to `interceptor`.
    * @param {Function} interceptor The function to invoke.
    * @returns {*} Returns the result of `interceptor`.
    * @example
    *
    * _('  abc  ')
    *  .chain()
    *  .trim()
    *  .thru(function(value) {
    *    return [value];
    *  })
    *  .value();
    * // => ['abc']
    */
   function thru(value, interceptor) {
     return interceptor(value);
   }
   /**
    * This method is the wrapper version of `_.at`.
    *
    * @name at
    * @memberOf _
    * @since 1.0.0
    * @category Seq
    * @param {...(string|string[])} [paths] The property paths to pick.
    * @returns {Object} Returns the new `lodash` wrapper instance.
    * @example
    *
    * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
    *
    * _(object).at(['a[0].b.c', 'a[1]']).value();
    * // => [3, 4]
    */
   var wrapperAt = flatRest(function(paths) {
     var length = paths.length,
         start = length ? paths[0] : 0,
         value = this.__wrapped__,
         interceptor = function(object) { return baseAt(object, paths); };
     if (length > 1 || this.__actions__.length ||
         !(value instanceof LazyWrapper) || !isIndex(start)) {
       return this.thru(interceptor);
     }
     value = value.slice(start, +start + (length ? 1 : 0));
     value.__actions__.push({
       'func': thru,
       'args': [interceptor],
       'thisArg': undefined
     });
     return new LodashWrapper(value, this.__chain__).thru(function(array) {
       if (length && !array.length) {
         array.push(undefined);
       }
       return array;
     });
   });
   /**
    * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
    *
    * @name chain
    * @memberOf _
    * @since 0.1.0
    * @category Seq
    * @returns {Object} Returns the new `lodash` wrapper instance.
    * @example
    *
    * var users = [
    *   { 'user': 'barney', 'age': 36 },
    *   { 'user': 'fred',   'age': 40 }
    * ];
    *
    * // A sequence without explicit chaining.
    * _(users).head();
    * // => { 'user': 'barney', 'age': 36 }
    *
    * // A sequence with explicit chaining.
    * _(users)
    *   .chain()
    *   .head()
    *   .pick('user')
    *   .value();
    * // => { 'user': 'barney' }
    */
   function wrapperChain() {
     return chain(this);
   }
   /**
    * Executes the chain sequence and returns the wrapped result.
    *
    * @name commit
    * @memberOf _
    * @since 3.2.0
    * @category Seq
    * @returns {Object} Returns the new `lodash` wrapper instance.
    * @example
    *
    * var array = [1, 2];
    * var wrapped = _(array).push(3);
    *
    * console.log(array);
    * // => [1, 2]
    *
    * wrapped = wrapped.commit();
    * console.log(array);
    * // => [1, 2, 3]
    *
    * wrapped.last();
    * // => 3
    *
    * console.log(array);
    * // => [1, 2, 3]
    */
   function wrapperCommit() {
     return new LodashWrapper(this.value(), this.__chain__);
   }
   /**
    * Gets the next value on a wrapped object following the
    * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
    *
    * @name next
    * @memberOf _
    * @since 4.0.0
    * @category Seq
    * @returns {Object} Returns the next iterator value.
    * @example
    *
    * var wrapped = _([1, 2]);
    *
    * wrapped.next();
    * // => { 'done': false, 'value': 1 }
    *
    * wrapped.next();
    * // => { 'done': false, 'value': 2 }
    *
    * wrapped.next();
    * // => { 'done': true, 'value': undefined }
    */
   function wrapperNext() {
     if (this.__values__ === undefined) {
       this.__values__ = toArray(this.value());
     }
     var done = this.__index__ >= this.__values__.length,
         value = done ? undefined : this.__values__[this.__index__++];
     return { 'done': done, 'value': value };
   }
   /**
    * Enables the wrapper to be iterable.
    *
    * @name Symbol.iterator
    * @memberOf _
    * @since 4.0.0
    * @category Seq
    * @returns {Object} Returns the wrapper object.
    * @example
    *
    * var wrapped = _([1, 2]);
    *
    * wrapped[Symbol.iterator]() === wrapped;
    * // => true
    *
    * Array.from(wrapped);
    * // => [1, 2]
    */
   function wrapperToIterator() {
     return this;
   }
   /**
    * Creates a clone of the chain sequence planting `value` as the wrapped value.
    *
    * @name plant
    * @memberOf _
    * @since 3.2.0
    * @category Seq
    * @param {*} value The value to plant.
    * @returns {Object} Returns the new `lodash` wrapper instance.
    * @example
    *
    * function square(n) {
    *   return n * n;
    * }
    *
    * var wrapped = _([1, 2]).map(square);
    * var other = wrapped.plant([3, 4]);
    *
    * other.value();
    * // => [9, 16]
    *
    * wrapped.value();
    * // => [1, 4]
    */
   function wrapperPlant(value) {
     var result,
         parent = this;
     while (parent instanceof baseLodash) {
       var clone = wrapperClone(parent);
       clone.__index__ = 0;
       clone.__values__ = undefined;
       if (result) {
         previous.__wrapped__ = clone;
       } else {
         result = clone;
       }
       var previous = clone;
       parent = parent.__wrapped__;
     }
     previous.__wrapped__ = value;
     return result;
   }
   /**
    * This method is the wrapper version of `_.reverse`.
    *
    * **Note:** This method mutates the wrapped array.
    *
    * @name reverse
    * @memberOf _
    * @since 0.1.0
    * @category Seq
    * @returns {Object} Returns the new `lodash` wrapper instance.
    * @example
    *
    * var array = [1, 2, 3];
    *
    * _(array).reverse().value()
    * // => [3, 2, 1]
    *
    * console.log(array);
    * // => [3, 2, 1]
    */
   function wrapperReverse() {
     var value = this.__wrapped__;
     if (value instanceof LazyWrapper) {
       var wrapped = value;
       if (this.__actions__.length) {
         wrapped = new LazyWrapper(this);
       }
       wrapped = wrapped.reverse();
       wrapped.__actions__.push({
         'func': thru,
         'args': [reverse],
         'thisArg': undefined
       });
       return new LodashWrapper(wrapped, this.__chain__);
     }
     return this.thru(reverse);
   }
   /**
    * Executes the chain sequence to resolve the unwrapped value.
    *
    * @name value
    * @memberOf _
    * @since 0.1.0
    * @alias toJSON, valueOf
    * @category Seq
    * @returns {*} Returns the resolved unwrapped value.
    * @example
    *
    * _([1, 2, 3]).value();
    * // => [1, 2, 3]
    */
   function wrapperValue() {
     return baseWrapperValue(this.__wrapped__, this.__actions__);
   }
   /*------------------------------------------------------------------------*/
   /**
    * Creates an object composed of keys generated from the results of running
    * each element of `collection` thru `iteratee`. The corresponding value of
    * each key is the number of times the key was returned by `iteratee`. The
    * iteratee is invoked with one argument: (value).
    *
    * @static
    * @memberOf _
    * @since 0.5.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
    * @returns {Object} Returns the composed aggregate object.
    * @example
    *
    * _.countBy([6.1, 4.2, 6.3], Math.floor);
    * // => { '4': 1, '6': 2 }
    *
    * // The `_.property` iteratee shorthand.
    * _.countBy(['one', 'two', 'three'], 'length');
    * // => { '3': 2, '5': 1 }
    */
   var countBy = createAggregator(function(result, value, key) {
     if (hasOwnProperty.call(result, key)) {
       ++result[key];
     } else {
       baseAssignValue(result, key, 1);
     }
   });
   /**
    * Checks if `predicate` returns truthy for **all** elements of `collection`.
    * Iteration is stopped once `predicate` returns falsey. The predicate is
    * invoked with three arguments: (value, index|key, collection).
    *
    * **Note:** This method returns `true` for
    * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
    * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
    * elements of empty collections.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {boolean} Returns `true` if all elements pass the predicate check,
    *  else `false`.
    * @example
    *
    * _.every([true, 1, null, 'yes'], Boolean);
    * // => false
    *
    * var users = [
    *   { 'user': 'barney', 'age': 36, 'active': false },
    *   { 'user': 'fred',   'age': 40, 'active': false }
    * ];
    *
    * // The `_.matches` iteratee shorthand.
    * _.every(users, { 'user': 'barney', 'active': false });
    * // => false
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.every(users, ['active', false]);
    * // => true
    *
    * // The `_.property` iteratee shorthand.
    * _.every(users, 'active');
    * // => false
    */
   function every(collection, predicate, guard) {
     var func = isArray(collection) ? arrayEvery : baseEvery;
     if (guard && isIterateeCall(collection, predicate, guard)) {
       predicate = undefined;
     }
     return func(collection, getIteratee(predicate, 3));
   }
   /**
    * Iterates over elements of `collection`, returning an array of all elements
    * `predicate` returns truthy for. The predicate is invoked with three
    * arguments: (value, index|key, collection).
    *
    * **Note:** Unlike `_.remove`, this method returns a new array.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the new filtered array.
    * @see _.reject
    * @example
    *
    * var users = [
    *   { 'user': 'barney', 'age': 36, 'active': true },
    *   { 'user': 'fred',   'age': 40, 'active': false }
    * ];
    *
    * _.filter(users, function(o) { return !o.active; });
    * // => objects for ['fred']
    *
    * // The `_.matches` iteratee shorthand.
    * _.filter(users, { 'age': 36, 'active': true });
    * // => objects for ['barney']
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.filter(users, ['active', false]);
    * // => objects for ['fred']
    *
    * // The `_.property` iteratee shorthand.
    * _.filter(users, 'active');
    * // => objects for ['barney']
    */
   function filter(collection, predicate) {
     var func = isArray(collection) ? arrayFilter : baseFilter;
     return func(collection, getIteratee(predicate, 3));
   }
   /**
    * Iterates over elements of `collection`, returning the first element
    * `predicate` returns truthy for. The predicate is invoked with three
    * arguments: (value, index|key, collection).
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to inspect.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @param {number} [fromIndex=0] The index to search from.
    * @returns {*} Returns the matched element, else `undefined`.
    * @example
    *
    * var users = [
    *   { 'user': 'barney',  'age': 36, 'active': true },
    *   { 'user': 'fred',    'age': 40, 'active': false },
    *   { 'user': 'pebbles', 'age': 1,  'active': true }
    * ];
    *
    * _.find(users, function(o) { return o.age < 40; });
    * // => object for 'barney'
    *
    * // The `_.matches` iteratee shorthand.
    * _.find(users, { 'age': 1, 'active': true });
    * // => object for 'pebbles'
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.find(users, ['active', false]);
    * // => object for 'fred'
    *
    * // The `_.property` iteratee shorthand.
    * _.find(users, 'active');
    * // => object for 'barney'
    */
   var find = createFind(findIndex);
   /**
    * This method is like `_.find` except that it iterates over elements of
    * `collection` from right to left.
    *
    * @static
    * @memberOf _
    * @since 2.0.0
    * @category Collection
    * @param {Array|Object} collection The collection to inspect.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @param {number} [fromIndex=collection.length-1] The index to search from.
    * @returns {*} Returns the matched element, else `undefined`.
    * @example
    *
    * _.findLast([1, 2, 3, 4], function(n) {
    *   return n % 2 == 1;
    * });
    * // => 3
    */
   var findLast = createFind(findLastIndex);
   /**
    * Creates a flattened array of values by running each element in `collection`
    * thru `iteratee` and flattening the mapped results. The iteratee is invoked
    * with three arguments: (value, index|key, collection).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the new flattened array.
    * @example
    *
    * function duplicate(n) {
    *   return [n, n];
    * }
    *
    * _.flatMap([1, 2], duplicate);
    * // => [1, 1, 2, 2]
    */
   function flatMap(collection, iteratee) {
     return baseFlatten(map(collection, iteratee), 1);
   }
   /**
    * This method is like `_.flatMap` except that it recursively flattens the
    * mapped results.
    *
    * @static
    * @memberOf _
    * @since 4.7.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the new flattened array.
    * @example
    *
    * function duplicate(n) {
    *   return [[[n, n]]];
    * }
    *
    * _.flatMapDeep([1, 2], duplicate);
    * // => [1, 1, 2, 2]
    */
   function flatMapDeep(collection, iteratee) {
     return baseFlatten(map(collection, iteratee), INFINITY);
   }
   /**
    * This method is like `_.flatMap` except that it recursively flattens the
    * mapped results up to `depth` times.
    *
    * @static
    * @memberOf _
    * @since 4.7.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @param {number} [depth=1] The maximum recursion depth.
    * @returns {Array} Returns the new flattened array.
    * @example
    *
    * function duplicate(n) {
    *   return [[[n, n]]];
    * }
    *
    * _.flatMapDepth([1, 2], duplicate, 2);
    * // => [[1, 1], [2, 2]]
    */
   function flatMapDepth(collection, iteratee, depth) {
     depth = depth === undefined ? 1 : toInteger(depth);
     return baseFlatten(map(collection, iteratee), depth);
   }
   /**
    * Iterates over elements of `collection` and invokes `iteratee` for each element.
    * The iteratee is invoked with three arguments: (value, index|key, collection).
    * Iteratee functions may exit iteration early by explicitly returning `false`.
    *
    * **Note:** As with other "Collections" methods, objects with a "length"
    * property are iterated like arrays. To avoid this behavior use `_.forIn`
    * or `_.forOwn` for object iteration.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @alias each
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Array|Object} Returns `collection`.
    * @see _.forEachRight
    * @example
    *
    * _.forEach([1, 2], function(value) {
    *   console.log(value);
    * });
    * // => Logs `1` then `2`.
    *
    * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
    *   console.log(key);
    * });
    * // => Logs 'a' then 'b' (iteration order is not guaranteed).
    */
   function forEach(collection, iteratee) {
     var func = isArray(collection) ? arrayEach : baseEach;
     return func(collection, getIteratee(iteratee, 3));
   }
   /**
    * This method is like `_.forEach` except that it iterates over elements of
    * `collection` from right to left.
    *
    * @static
    * @memberOf _
    * @since 2.0.0
    * @alias eachRight
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Array|Object} Returns `collection`.
    * @see _.forEach
    * @example
    *
    * _.forEachRight([1, 2], function(value) {
    *   console.log(value);
    * });
    * // => Logs `2` then `1`.
    */
   function forEachRight(collection, iteratee) {
     var func = isArray(collection) ? arrayEachRight : baseEachRight;
     return func(collection, getIteratee(iteratee, 3));
   }
   /**
    * Creates an object composed of keys generated from the results of running
    * each element of `collection` thru `iteratee`. The order of grouped values
    * is determined by the order they occur in `collection`. The corresponding
    * value of each key is an array of elements responsible for generating the
    * key. The iteratee is invoked with one argument: (value).
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
    * @returns {Object} Returns the composed aggregate object.
    * @example
    *
    * _.groupBy([6.1, 4.2, 6.3], Math.floor);
    * // => { '4': [4.2], '6': [6.1, 6.3] }
    *
    * // The `_.property` iteratee shorthand.
    * _.groupBy(['one', 'two', 'three'], 'length');
    * // => { '3': ['one', 'two'], '5': ['three'] }
    */
   var groupBy = createAggregator(function(result, value, key) {
     if (hasOwnProperty.call(result, key)) {
       result[key].push(value);
     } else {
       baseAssignValue(result, key, [value]);
     }
   });
   /**
    * Checks if `value` is in `collection`. If `collection` is a string, it's
    * checked for a substring of `value`, otherwise
    * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
    * is used for equality comparisons. If `fromIndex` is negative, it's used as
    * the offset from the end of `collection`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object|string} collection The collection to inspect.
    * @param {*} value The value to search for.
    * @param {number} [fromIndex=0] The index to search from.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
    * @returns {boolean} Returns `true` if `value` is found, else `false`.
    * @example
    *
    * _.includes([1, 2, 3], 1);
    * // => true
    *
    * _.includes([1, 2, 3], 1, 2);
    * // => false
    *
    * _.includes({ 'a': 1, 'b': 2 }, 1);
    * // => true
    *
    * _.includes('abcd', 'bc');
    * // => true
    */
   function includes(collection, value, fromIndex, guard) {
     collection = isArrayLike(collection) ? collection : values(collection);
     fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
     var length = collection.length;
     if (fromIndex < 0) {
       fromIndex = nativeMax(length + fromIndex, 0);
     }
     return isString(collection)
       ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
       : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
   }
   /**
    * Invokes the method at `path` of each element in `collection`, returning
    * an array of the results of each invoked method. Any additional arguments
    * are provided to each invoked method. If `path` is a function, it's invoked
    * for, and `this` bound to, each element in `collection`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Array|Function|string} path The path of the method to invoke or
    *  the function invoked per iteration.
    * @param {...*} [args] The arguments to invoke each method with.
    * @returns {Array} Returns the array of results.
    * @example
    *
    * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
    * // => [[1, 5, 7], [1, 2, 3]]
    *
    * _.invokeMap([123, 456], String.prototype.split, );
    * // => [['1', '2', '3'], ['4', '5', '6']]
    */
   var invokeMap = baseRest(function(collection, path, args) {
     var index = -1,
         isFunc = typeof path == 'function',
         result = isArrayLike(collection) ? Array(collection.length) : [];
     baseEach(collection, function(value) {
       result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
     });
     return result;
   });
   /**
    * Creates an object composed of keys generated from the results of running
    * each element of `collection` thru `iteratee`. The corresponding value of
    * each key is the last element responsible for generating the key. The
    * iteratee is invoked with one argument: (value).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
    * @returns {Object} Returns the composed aggregate object.
    * @example
    *
    * var array = [
    *   { 'dir': 'left', 'code': 97 },
    *   { 'dir': 'right', 'code': 100 }
    * ];
    *
    * _.keyBy(array, function(o) {
    *   return String.fromCharCode(o.code);
    * });
    * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
    *
    * _.keyBy(array, 'dir');
    * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
    */
   var keyBy = createAggregator(function(result, value, key) {
     baseAssignValue(result, key, value);
   });
   /**
    * Creates an array of values by running each element in `collection` thru
    * `iteratee`. The iteratee is invoked with three arguments:
    * (value, index|key, collection).
    *
    * Many lodash methods are guarded to work as iteratees for methods like
    * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
    *
    * The guarded methods are:
    * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
    * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
    * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
    * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the new mapped array.
    * @example
    *
    * function square(n) {
    *   return n * n;
    * }
    *
    * _.map([4, 8], square);
    * // => [16, 64]
    *
    * _.map({ 'a': 4, 'b': 8 }, square);
    * // => [16, 64] (iteration order is not guaranteed)
    *
    * var users = [
    *   { 'user': 'barney' },
    *   { 'user': 'fred' }
    * ];
    *
    * // The `_.property` iteratee shorthand.
    * _.map(users, 'user');
    * // => ['barney', 'fred']
    */
   function map(collection, iteratee) {
     var func = isArray(collection) ? arrayMap : baseMap;
     return func(collection, getIteratee(iteratee, 3));
   }
   /**
    * This method is like `_.sortBy` except that it allows specifying the sort
    * orders of the iteratees to sort by. If `orders` is unspecified, all values
    * are sorted in ascending order. Otherwise, specify an order of "desc" for
    * descending or "asc" for ascending sort order of corresponding values.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
    *  The iteratees to sort by.
    * @param {string[]} [orders] The sort orders of `iteratees`.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
    * @returns {Array} Returns the new sorted array.
    * @example
    *
    * var users = [
    *   { 'user': 'fred',   'age': 48 },
    *   { 'user': 'barney', 'age': 34 },
    *   { 'user': 'fred',   'age': 40 },
    *   { 'user': 'barney', 'age': 36 }
    * ];
    *
    * // Sort by `user` in ascending order and by `age` in descending order.
    * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
    * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
    */
   function orderBy(collection, iteratees, orders, guard) {
     if (collection == null) {
       return [];
     }
     if (!isArray(iteratees)) {
       iteratees = iteratees == null ? [] : [iteratees];
     }
     orders = guard ? undefined : orders;
     if (!isArray(orders)) {
       orders = orders == null ? [] : [orders];
     }
     return baseOrderBy(collection, iteratees, orders);
   }
   /**
    * Creates an array of elements split into two groups, the first of which
    * contains elements `predicate` returns truthy for, the second of which
    * contains elements `predicate` returns falsey for. The predicate is
    * invoked with one argument: (value).
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the array of grouped elements.
    * @example
    *
    * var users = [
    *   { 'user': 'barney',  'age': 36, 'active': false },
    *   { 'user': 'fred',    'age': 40, 'active': true },
    *   { 'user': 'pebbles', 'age': 1,  'active': false }
    * ];
    *
    * _.partition(users, function(o) { return o.active; });
    * // => objects for [['fred'], ['barney', 'pebbles']]
    *
    * // The `_.matches` iteratee shorthand.
    * _.partition(users, { 'age': 1, 'active': false });
    * // => objects for [['pebbles'], ['barney', 'fred']]
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.partition(users, ['active', false]);
    * // => objects for [['barney', 'pebbles'], ['fred']]
    *
    * // The `_.property` iteratee shorthand.
    * _.partition(users, 'active');
    * // => objects for [['fred'], ['barney', 'pebbles']]
    */
   var partition = createAggregator(function(result, value, key) {
     result[key ? 0 : 1].push(value);
   }, function() { return [[], []]; });
   /**
    * Reduces `collection` to a value which is the accumulated result of running
    * each element in `collection` thru `iteratee`, where each successive
    * invocation is supplied the return value of the previous. If `accumulator`
    * is not given, the first element of `collection` is used as the initial
    * value. The iteratee is invoked with four arguments:
    * (accumulator, value, index|key, collection).
    *
    * Many lodash methods are guarded to work as iteratees for methods like
    * `_.reduce`, `_.reduceRight`, and `_.transform`.
    *
    * The guarded methods are:
    * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
    * and `sortBy`
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @param {*} [accumulator] The initial value.
    * @returns {*} Returns the accumulated value.
    * @see _.reduceRight
    * @example
    *
    * _.reduce([1, 2], function(sum, n) {
    *   return sum + n;
    * }, 0);
    * // => 3
    *
    * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
    *   (result[value] || (result[value] = [])).push(key);
    *   return result;
    * }, {});
    * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
    */
   function reduce(collection, iteratee, accumulator) {
     var func = isArray(collection) ? arrayReduce : baseReduce,
         initAccum = arguments.length < 3;
     return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
   }
   /**
    * This method is like `_.reduce` except that it iterates over elements of
    * `collection` from right to left.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @param {*} [accumulator] The initial value.
    * @returns {*} Returns the accumulated value.
    * @see _.reduce
    * @example
    *
    * var array = [[0, 1], [2, 3], [4, 5]];
    *
    * _.reduceRight(array, function(flattened, other) {
    *   return flattened.concat(other);
    * }, []);
    * // => [4, 5, 2, 3, 0, 1]
    */
   function reduceRight(collection, iteratee, accumulator) {
     var func = isArray(collection) ? arrayReduceRight : baseReduce,
         initAccum = arguments.length < 3;
     return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
   }
   /**
    * The opposite of `_.filter`; this method returns the elements of `collection`
    * that `predicate` does **not** return truthy for.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @returns {Array} Returns the new filtered array.
    * @see _.filter
    * @example
    *
    * var users = [
    *   { 'user': 'barney', 'age': 36, 'active': false },
    *   { 'user': 'fred',   'age': 40, 'active': true }
    * ];
    *
    * _.reject(users, function(o) { return !o.active; });
    * // => objects for ['fred']
    *
    * // The `_.matches` iteratee shorthand.
    * _.reject(users, { 'age': 40, 'active': true });
    * // => objects for ['barney']
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.reject(users, ['active', false]);
    * // => objects for ['fred']
    *
    * // The `_.property` iteratee shorthand.
    * _.reject(users, 'active');
    * // => objects for ['barney']
    */
   function reject(collection, predicate) {
     var func = isArray(collection) ? arrayFilter : baseFilter;
     return func(collection, negate(getIteratee(predicate, 3)));
   }
   /**
    * Gets a random element from `collection`.
    *
    * @static
    * @memberOf _
    * @since 2.0.0
    * @category Collection
    * @param {Array|Object} collection The collection to sample.
    * @returns {*} Returns the random element.
    * @example
    *
    * _.sample([1, 2, 3, 4]);
    * // => 2
    */
   function sample(collection) {
     var func = isArray(collection) ? arraySample : baseSample;
     return func(collection);
   }
   /**
    * Gets `n` random elements at unique keys from `collection` up to the
    * size of `collection`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Collection
    * @param {Array|Object} collection The collection to sample.
    * @param {number} [n=1] The number of elements to sample.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {Array} Returns the random elements.
    * @example
    *
    * _.sampleSize([1, 2, 3], 2);
    * // => [3, 1]
    *
    * _.sampleSize([1, 2, 3], 4);
    * // => [2, 3, 1]
    */
   function sampleSize(collection, n, guard) {
     if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
       n = 1;
     } else {
       n = toInteger(n);
     }
     var func = isArray(collection) ? arraySampleSize : baseSampleSize;
     return func(collection, n);
   }
   /**
    * Creates an array of shuffled values, using a version of the
    * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to shuffle.
    * @returns {Array} Returns the new shuffled array.
    * @example
    *
    * _.shuffle([1, 2, 3, 4]);
    * // => [4, 1, 3, 2]
    */
   function shuffle(collection) {
     var func = isArray(collection) ? arrayShuffle : baseShuffle;
     return func(collection);
   }
   /**
    * Gets the size of `collection` by returning its length for array-like
    * values or the number of own enumerable string keyed properties for objects.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object|string} collection The collection to inspect.
    * @returns {number} Returns the collection size.
    * @example
    *
    * _.size([1, 2, 3]);
    * // => 3
    *
    * _.size({ 'a': 1, 'b': 2 });
    * // => 2
    *
    * _.size('pebbles');
    * // => 7
    */
   function size(collection) {
     if (collection == null) {
       return 0;
     }
     if (isArrayLike(collection)) {
       return isString(collection) ? stringSize(collection) : collection.length;
     }
     var tag = getTag(collection);
     if (tag == mapTag || tag == setTag) {
       return collection.size;
     }
     return baseKeys(collection).length;
   }
   /**
    * Checks if `predicate` returns truthy for **any** element of `collection`.
    * Iteration is stopped once `predicate` returns truthy. The predicate is
    * invoked with three arguments: (value, index|key, collection).
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {boolean} Returns `true` if any element passes the predicate check,
    *  else `false`.
    * @example
    *
    * _.some([null, 0, 'yes', false], Boolean);
    * // => true
    *
    * var users = [
    *   { 'user': 'barney', 'active': true },
    *   { 'user': 'fred',   'active': false }
    * ];
    *
    * // The `_.matches` iteratee shorthand.
    * _.some(users, { 'user': 'barney', 'active': false });
    * // => false
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.some(users, ['active', false]);
    * // => true
    *
    * // The `_.property` iteratee shorthand.
    * _.some(users, 'active');
    * // => true
    */
   function some(collection, predicate, guard) {
     var func = isArray(collection) ? arraySome : baseSome;
     if (guard && isIterateeCall(collection, predicate, guard)) {
       predicate = undefined;
     }
     return func(collection, getIteratee(predicate, 3));
   }
   /**
    * Creates an array of elements, sorted in ascending order by the results of
    * running each element in a collection thru each iteratee. This method
    * performs a stable sort, that is, it preserves the original sort order of
    * equal elements. The iteratees are invoked with one argument: (value).
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Collection
    * @param {Array|Object} collection The collection to iterate over.
    * @param {...(Function|Function[])} [iteratees=[_.identity]]
    *  The iteratees to sort by.
    * @returns {Array} Returns the new sorted array.
    * @example
    *
    * var users = [
    *   { 'user': 'fred',   'age': 48 },
    *   { 'user': 'barney', 'age': 36 },
    *   { 'user': 'fred',   'age': 40 },
    *   { 'user': 'barney', 'age': 34 }
    * ];
    *
    * _.sortBy(users, [function(o) { return o.user; }]);
    * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
    *
    * _.sortBy(users, ['user', 'age']);
    * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
    */
   var sortBy = baseRest(function(collection, iteratees) {
     if (collection == null) {
       return [];
     }
     var length = iteratees.length;
     if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
       iteratees = [];
     } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
       iteratees = [iteratees[0]];
     }
     return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
   });
   /*------------------------------------------------------------------------*/
   /**
    * Gets the timestamp of the number of milliseconds that have elapsed since
    * the Unix epoch (1 January 1970 00:00:00 UTC).
    *
    * @static
    * @memberOf _
    * @since 2.4.0
    * @category Date
    * @returns {number} Returns the timestamp.
    * @example
    *
    * _.defer(function(stamp) {
    *   console.log(_.now() - stamp);
    * }, _.now());
    * // => Logs the number of milliseconds it took for the deferred invocation.
    */
   var now = ctxNow || function() {
     return root.Date.now();
   };
   /*------------------------------------------------------------------------*/
   /**
    * The opposite of `_.before`; this method creates a function that invokes
    * `func` once it's called `n` or more times.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Function
    * @param {number} n The number of calls before `func` is invoked.
    * @param {Function} func The function to restrict.
    * @returns {Function} Returns the new restricted function.
    * @example
    *
    * var saves = ['profile', 'settings'];
    *
    * var done = _.after(saves.length, function() {
    *   console.log('done saving!');
    * });
    *
    * _.forEach(saves, function(type) {
    *   asyncSave({ 'type': type, 'complete': done });
    * });
    * // => Logs 'done saving!' after the two async saves have completed.
    */
   function after(n, func) {
     if (typeof func != 'function') {
       throw new TypeError(FUNC_ERROR_TEXT);
     }
     n = toInteger(n);
     return function() {
       if (--n < 1) {
         return func.apply(this, arguments);
       }
     };
   }
   /**
    * Creates a function that invokes `func`, with up to `n` arguments,
    * ignoring any additional arguments.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Function
    * @param {Function} func The function to cap arguments for.
    * @param {number} [n=func.length] The arity cap.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {Function} Returns the new capped function.
    * @example
    *
    * _.map(['6', '8', '10'], _.ary(parseInt, 1));
    * // => [6, 8, 10]
    */
   function ary(func, n, guard) {
     n = guard ? undefined : n;
     n = (func && n == null) ? func.length : n;
     return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
   }
   /**
    * Creates a function that invokes `func`, with the `this` binding and arguments
    * of the created function, while it's called less than `n` times. Subsequent
    * calls to the created function return the result of the last `func` invocation.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Function
    * @param {number} n The number of calls at which `func` is no longer invoked.
    * @param {Function} func The function to restrict.
    * @returns {Function} Returns the new restricted function.
    * @example
    *
    * jQuery(element).on('click', _.before(5, addContactToList));
    * // => Allows adding up to 4 contacts to the list.
    */
   function before(n, func) {
     var result;
     if (typeof func != 'function') {
       throw new TypeError(FUNC_ERROR_TEXT);
     }
     n = toInteger(n);
     return function() {
       if (--n > 0) {
         result = func.apply(this, arguments);
       }
       if (n <= 1) {
         func = undefined;
       }
       return result;
     };
   }
   /**
    * Creates a function that invokes `func` with the `this` binding of `thisArg`
    * and `partials` prepended to the arguments it receives.
    *
    * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
    * may be used as a placeholder for partially applied arguments.
    *
    * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
    * property of bound functions.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Function
    * @param {Function} func The function to bind.
    * @param {*} thisArg The `this` binding of `func`.
    * @param {...*} [partials] The arguments to be partially applied.
    * @returns {Function} Returns the new bound function.
    * @example
    *
    * function greet(greeting, punctuation) {
    *   return greeting + ' ' + this.user + punctuation;
    * }
    *
    * var object = { 'user': 'fred' };
    *
    * var bound = _.bind(greet, object, 'hi');
    * bound('!');
    * // => 'hi fred!'
    *
    * // Bound with placeholders.
    * var bound = _.bind(greet, object, _, '!');
    * bound('hi');
    * // => 'hi fred!'
    */
   var bind = baseRest(function(func, thisArg, partials) {
     var bitmask = WRAP_BIND_FLAG;
     if (partials.length) {
       var holders = replaceHolders(partials, getHolder(bind));
       bitmask |= WRAP_PARTIAL_FLAG;
     }
     return createWrap(func, bitmask, thisArg, partials, holders);
   });
   /**
    * Creates a function that invokes the method at `object[key]` with `partials`
    * prepended to the arguments it receives.
    *
    * This method differs from `_.bind` by allowing bound functions to reference
    * methods that may be redefined or don't yet exist. See
    * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
    * for more details.
    *
    * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
    * builds, may be used as a placeholder for partially applied arguments.
    *
    * @static
    * @memberOf _
    * @since 0.10.0
    * @category Function
    * @param {Object} object The object to invoke the method on.
    * @param {string} key The key of the method.
    * @param {...*} [partials] The arguments to be partially applied.
    * @returns {Function} Returns the new bound function.
    * @example
    *
    * var object = {
    *   'user': 'fred',
    *   'greet': function(greeting, punctuation) {
    *     return greeting + ' ' + this.user + punctuation;
    *   }
    * };
    *
    * var bound = _.bindKey(object, 'greet', 'hi');
    * bound('!');
    * // => 'hi fred!'
    *
    * object.greet = function(greeting, punctuation) {
    *   return greeting + 'ya ' + this.user + punctuation;
    * };
    *
    * bound('!');
    * // => 'hiya fred!'
    *
    * // Bound with placeholders.
    * var bound = _.bindKey(object, 'greet', _, '!');
    * bound('hi');
    * // => 'hiya fred!'
    */
   var bindKey = baseRest(function(object, key, partials) {
     var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
     if (partials.length) {
       var holders = replaceHolders(partials, getHolder(bindKey));
       bitmask |= WRAP_PARTIAL_FLAG;
     }
     return createWrap(key, bitmask, object, partials, holders);
   });
   /**
    * Creates a function that accepts arguments of `func` and either invokes
    * `func` returning its result, if at least `arity` number of arguments have
    * been provided, or returns a function that accepts the remaining `func`
    * arguments, and so on. The arity of `func` may be specified if `func.length`
    * is not sufficient.
    *
    * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
    * may be used as a placeholder for provided arguments.
    *
    * **Note:** This method doesn't set the "length" property of curried functions.
    *
    * @static
    * @memberOf _
    * @since 2.0.0
    * @category Function
    * @param {Function} func The function to curry.
    * @param {number} [arity=func.length] The arity of `func`.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {Function} Returns the new curried function.
    * @example
    *
    * var abc = function(a, b, c) {
    *   return [a, b, c];
    * };
    *
    * var curried = _.curry(abc);
    *
    * curried(1)(2)(3);
    * // => [1, 2, 3]
    *
    * curried(1, 2)(3);
    * // => [1, 2, 3]
    *
    * curried(1, 2, 3);
    * // => [1, 2, 3]
    *
    * // Curried with placeholders.
    * curried(1)(_, 3)(2);
    * // => [1, 2, 3]
    */
   function curry(func, arity, guard) {
     arity = guard ? undefined : arity;
     var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
     result.placeholder = curry.placeholder;
     return result;
   }
   /**
    * This method is like `_.curry` except that arguments are applied to `func`
    * in the manner of `_.partialRight` instead of `_.partial`.
    *
    * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
    * builds, may be used as a placeholder for provided arguments.
    *
    * **Note:** This method doesn't set the "length" property of curried functions.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Function
    * @param {Function} func The function to curry.
    * @param {number} [arity=func.length] The arity of `func`.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {Function} Returns the new curried function.
    * @example
    *
    * var abc = function(a, b, c) {
    *   return [a, b, c];
    * };
    *
    * var curried = _.curryRight(abc);
    *
    * curried(3)(2)(1);
    * // => [1, 2, 3]
    *
    * curried(2, 3)(1);
    * // => [1, 2, 3]
    *
    * curried(1, 2, 3);
    * // => [1, 2, 3]
    *
    * // Curried with placeholders.
    * curried(3)(1, _)(2);
    * // => [1, 2, 3]
    */
   function curryRight(func, arity, guard) {
     arity = guard ? undefined : arity;
     var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
     result.placeholder = curryRight.placeholder;
     return result;
   }
   /**
    * Creates a debounced function that delays invoking `func` until after `wait`
    * milliseconds have elapsed since the last time the debounced function was
    * invoked. The debounced function comes with a `cancel` method to cancel
    * delayed `func` invocations and a `flush` method to immediately invoke them.
    * Provide `options` to indicate whether `func` should be invoked on the
    * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
    * with the last arguments provided to the debounced function. Subsequent
    * calls to the debounced function return the result of the last `func`
    * invocation.
    *
    * **Note:** If `leading` and `trailing` options are `true`, `func` is
    * invoked on the trailing edge of the timeout only if the debounced function
    * is invoked more than once during the `wait` timeout.
    *
    * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
    * until to the next tick, similar to `setTimeout` with a timeout of `0`.
    *
    * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
    * for details over the differences between `_.debounce` and `_.throttle`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Function
    * @param {Function} func The function to debounce.
    * @param {number} [wait=0] The number of milliseconds to delay.
    * @param {Object} [options={}] The options object.
    * @param {boolean} [options.leading=false]
    *  Specify invoking on the leading edge of the timeout.
    * @param {number} [options.maxWait]
    *  The maximum time `func` is allowed to be delayed before it's invoked.
    * @param {boolean} [options.trailing=true]
    *  Specify invoking on the trailing edge of the timeout.
    * @returns {Function} Returns the new debounced function.
    * @example
    *
    * // Avoid costly calculations while the window size is in flux.
    * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
    *
    * // Invoke `sendMail` when clicked, debouncing subsequent calls.
    * jQuery(element).on('click', _.debounce(sendMail, 300, {
    *   'leading': true,
    *   'trailing': false
    * }));
    *
    * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
    * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
    * var source = new EventSource('/stream');
    * jQuery(source).on('message', debounced);
    *
    * // Cancel the trailing debounced invocation.
    * jQuery(window).on('popstate', debounced.cancel);
    */
   function debounce(func, wait, options) {
     var lastArgs,
         lastThis,
         maxWait,
         result,
         timerId,
         lastCallTime,
         lastInvokeTime = 0,
         leading = false,
         maxing = false,
         trailing = true;
     if (typeof func != 'function') {
       throw new TypeError(FUNC_ERROR_TEXT);
     }
     wait = toNumber(wait) || 0;
     if (isObject(options)) {
       leading = !!options.leading;
       maxing = 'maxWait' in options;
       maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
       trailing = 'trailing' in options ? !!options.trailing : trailing;
     }
     function invokeFunc(time) {
       var args = lastArgs,
           thisArg = lastThis;
       lastArgs = lastThis = undefined;
       lastInvokeTime = time;
       result = func.apply(thisArg, args);
       return result;
     }
     function leadingEdge(time) {
       // Reset any `maxWait` timer.
       lastInvokeTime = time;
       // Start the timer for the trailing edge.
       timerId = setTimeout(timerExpired, wait);
       // Invoke the leading edge.
       return leading ? invokeFunc(time) : result;
     }
     function remainingWait(time) {
       var timeSinceLastCall = time - lastCallTime,
           timeSinceLastInvoke = time - lastInvokeTime,
           timeWaiting = wait - timeSinceLastCall;
       return maxing
         ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
         : timeWaiting;
     }
     function shouldInvoke(time) {
       var timeSinceLastCall = time - lastCallTime,
           timeSinceLastInvoke = time - lastInvokeTime;
       // Either this is the first call, activity has stopped and we're at the
       // trailing edge, the system time has gone backwards and we're treating
       // it as the trailing edge, or we've hit the `maxWait` limit.
       return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
         (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
     }
     function timerExpired() {
       var time = now();
       if (shouldInvoke(time)) {
         return trailingEdge(time);
       }
       // Restart the timer.
       timerId = setTimeout(timerExpired, remainingWait(time));
     }
     function trailingEdge(time) {
       timerId = undefined;
       // Only invoke if we have `lastArgs` which means `func` has been
       // debounced at least once.
       if (trailing && lastArgs) {
         return invokeFunc(time);
       }
       lastArgs = lastThis = undefined;
       return result;
     }
     function cancel() {
       if (timerId !== undefined) {
         clearTimeout(timerId);
       }
       lastInvokeTime = 0;
       lastArgs = lastCallTime = lastThis = timerId = undefined;
     }
     function flush() {
       return timerId === undefined ? result : trailingEdge(now());
     }
     function debounced() {
       var time = now(),
           isInvoking = shouldInvoke(time);
       lastArgs = arguments;
       lastThis = this;
       lastCallTime = time;
       if (isInvoking) {
         if (timerId === undefined) {
           return leadingEdge(lastCallTime);
         }
         if (maxing) {
           // Handle invocations in a tight loop.
           clearTimeout(timerId);
           timerId = setTimeout(timerExpired, wait);
           return invokeFunc(lastCallTime);
         }
       }
       if (timerId === undefined) {
         timerId = setTimeout(timerExpired, wait);
       }
       return result;
     }
     debounced.cancel = cancel;
     debounced.flush = flush;
     return debounced;
   }
   /**
    * Defers invoking the `func` until the current call stack has cleared. Any
    * additional arguments are provided to `func` when it's invoked.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Function
    * @param {Function} func The function to defer.
    * @param {...*} [args] The arguments to invoke `func` with.
    * @returns {number} Returns the timer id.
    * @example
    *
    * _.defer(function(text) {
    *   console.log(text);
    * }, 'deferred');
    * // => Logs 'deferred' after one millisecond.
    */
   var defer = baseRest(function(func, args) {
     return baseDelay(func, 1, args);
   });
   /**
    * Invokes `func` after `wait` milliseconds. Any additional arguments are
    * provided to `func` when it's invoked.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Function
    * @param {Function} func The function to delay.
    * @param {number} wait The number of milliseconds to delay invocation.
    * @param {...*} [args] The arguments to invoke `func` with.
    * @returns {number} Returns the timer id.
    * @example
    *
    * _.delay(function(text) {
    *   console.log(text);
    * }, 1000, 'later');
    * // => Logs 'later' after one second.
    */
   var delay = baseRest(function(func, wait, args) {
     return baseDelay(func, toNumber(wait) || 0, args);
   });
   /**
    * Creates a function that invokes `func` with arguments reversed.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Function
    * @param {Function} func The function to flip arguments for.
    * @returns {Function} Returns the new flipped function.
    * @example
    *
    * var flipped = _.flip(function() {
    *   return _.toArray(arguments);
    * });
    *
    * flipped('a', 'b', 'c', 'd');
    * // => ['d', 'c', 'b', 'a']
    */
   function flip(func) {
     return createWrap(func, WRAP_FLIP_FLAG);
   }
   /**
    * Creates a function that memoizes the result of `func`. If `resolver` is
    * provided, it determines the cache key for storing the result based on the
    * arguments provided to the memoized function. By default, the first argument
    * provided to the memoized function is used as the map cache key. The `func`
    * is invoked with the `this` binding of the memoized function.
    *
    * **Note:** The cache is exposed as the `cache` property on the memoized
    * function. Its creation may be customized by replacing the `_.memoize.Cache`
    * constructor with one whose instances implement the
    * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
    * method interface of `clear`, `delete`, `get`, `has`, and `set`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Function
    * @param {Function} func The function to have its output memoized.
    * @param {Function} [resolver] The function to resolve the cache key.
    * @returns {Function} Returns the new memoized function.
    * @example
    *
    * var object = { 'a': 1, 'b': 2 };
    * var other = { 'c': 3, 'd': 4 };
    *
    * var values = _.memoize(_.values);
    * values(object);
    * // => [1, 2]
    *
    * values(other);
    * // => [3, 4]
    *
    * object.a = 2;
    * values(object);
    * // => [1, 2]
    *
    * // Modify the result cache.
    * values.cache.set(object, ['a', 'b']);
    * values(object);
    * // => ['a', 'b']
    *
    * // Replace `_.memoize.Cache`.
    * _.memoize.Cache = WeakMap;
    */
   function memoize(func, resolver) {
     if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
       throw new TypeError(FUNC_ERROR_TEXT);
     }
     var memoized = function() {
       var args = arguments,
           key = resolver ? resolver.apply(this, args) : args[0],
           cache = memoized.cache;
       if (cache.has(key)) {
         return cache.get(key);
       }
       var result = func.apply(this, args);
       memoized.cache = cache.set(key, result) || cache;
       return result;
     };
     memoized.cache = new (memoize.Cache || MapCache);
     return memoized;
   }
   // Expose `MapCache`.
   memoize.Cache = MapCache;
   /**
    * Creates a function that negates the result of the predicate `func`. The
    * `func` predicate is invoked with the `this` binding and arguments of the
    * created function.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Function
    * @param {Function} predicate The predicate to negate.
    * @returns {Function} Returns the new negated function.
    * @example
    *
    * function isEven(n) {
    *   return n % 2 == 0;
    * }
    *
    * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
    * // => [1, 3, 5]
    */
   function negate(predicate) {
     if (typeof predicate != 'function') {
       throw new TypeError(FUNC_ERROR_TEXT);
     }
     return function() {
       var args = arguments;
       switch (args.length) {
         case 0: return !predicate.call(this);
         case 1: return !predicate.call(this, args[0]);
         case 2: return !predicate.call(this, args[0], args[1]);
         case 3: return !predicate.call(this, args[0], args[1], args[2]);
       }
       return !predicate.apply(this, args);
     };
   }
   /**
    * Creates a function that is restricted to invoking `func` once. Repeat calls
    * to the function return the value of the first invocation. The `func` is
    * invoked with the `this` binding and arguments of the created function.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Function
    * @param {Function} func The function to restrict.
    * @returns {Function} Returns the new restricted function.
    * @example
    *
    * var initialize = _.once(createApplication);
    * initialize();
    * initialize();
    * // => `createApplication` is invoked once
    */
   function once(func) {
     return before(2, func);
   }
   /**
    * Creates a function that invokes `func` with its arguments transformed.
    *
    * @static
    * @since 4.0.0
    * @memberOf _
    * @category Function
    * @param {Function} func The function to wrap.
    * @param {...(Function|Function[])} [transforms=[_.identity]]
    *  The argument transforms.
    * @returns {Function} Returns the new function.
    * @example
    *
    * function doubled(n) {
    *   return n * 2;
    * }
    *
    * function square(n) {
    *   return n * n;
    * }
    *
    * var func = _.overArgs(function(x, y) {
    *   return [x, y];
    * }, [square, doubled]);
    *
    * func(9, 3);
    * // => [81, 6]
    *
    * func(10, 5);
    * // => [100, 10]
    */
   var overArgs = castRest(function(func, transforms) {
     transforms = (transforms.length == 1 && isArray(transforms[0]))
       ? arrayMap(transforms[0], baseUnary(getIteratee()))
       : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
     var funcsLength = transforms.length;
     return baseRest(function(args) {
       var index = -1,
           length = nativeMin(args.length, funcsLength);
       while (++index < length) {
         args[index] = transforms[index].call(this, args[index]);
       }
       return apply(func, this, args);
     });
   });
   /**
    * Creates a function that invokes `func` with `partials` prepended to the
    * arguments it receives. This method is like `_.bind` except it does **not**
    * alter the `this` binding.
    *
    * The `_.partial.placeholder` value, which defaults to `_` in monolithic
    * builds, may be used as a placeholder for partially applied arguments.
    *
    * **Note:** This method doesn't set the "length" property of partially
    * applied functions.
    *
    * @static
    * @memberOf _
    * @since 0.2.0
    * @category Function
    * @param {Function} func The function to partially apply arguments to.
    * @param {...*} [partials] The arguments to be partially applied.
    * @returns {Function} Returns the new partially applied function.
    * @example
    *
    * function greet(greeting, name) {
    *   return greeting + ' ' + name;
    * }
    *
    * var sayHelloTo = _.partial(greet, 'hello');
    * sayHelloTo('fred');
    * // => 'hello fred'
    *
    * // Partially applied with placeholders.
    * var greetFred = _.partial(greet, _, 'fred');
    * greetFred('hi');
    * // => 'hi fred'
    */
   var partial = baseRest(function(func, partials) {
     var holders = replaceHolders(partials, getHolder(partial));
     return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
   });
   /**
    * This method is like `_.partial` except that partially applied arguments
    * are appended to the arguments it receives.
    *
    * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
    * builds, may be used as a placeholder for partially applied arguments.
    *
    * **Note:** This method doesn't set the "length" property of partially
    * applied functions.
    *
    * @static
    * @memberOf _
    * @since 1.0.0
    * @category Function
    * @param {Function} func The function to partially apply arguments to.
    * @param {...*} [partials] The arguments to be partially applied.
    * @returns {Function} Returns the new partially applied function.
    * @example
    *
    * function greet(greeting, name) {
    *   return greeting + ' ' + name;
    * }
    *
    * var greetFred = _.partialRight(greet, 'fred');
    * greetFred('hi');
    * // => 'hi fred'
    *
    * // Partially applied with placeholders.
    * var sayHelloTo = _.partialRight(greet, 'hello', _);
    * sayHelloTo('fred');
    * // => 'hello fred'
    */
   var partialRight = baseRest(function(func, partials) {
     var holders = replaceHolders(partials, getHolder(partialRight));
     return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
   });
   /**
    * Creates a function that invokes `func` with arguments arranged according
    * to the specified `indexes` where the argument value at the first index is
    * provided as the first argument, the argument value at the second index is
    * provided as the second argument, and so on.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Function
    * @param {Function} func The function to rearrange arguments for.
    * @param {...(number|number[])} indexes The arranged argument indexes.
    * @returns {Function} Returns the new function.
    * @example
    *
    * var rearged = _.rearg(function(a, b, c) {
    *   return [a, b, c];
    * }, [2, 0, 1]);
    *
    * rearged('b', 'c', 'a')
    * // => ['a', 'b', 'c']
    */
   var rearg = flatRest(function(func, indexes) {
     return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
   });
   /**
    * Creates a function that invokes `func` with the `this` binding of the
    * created function and arguments from `start` and beyond provided as
    * an array.
    *
    * **Note:** This method is based on the
    * [rest parameter](https://mdn.io/rest_parameters).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Function
    * @param {Function} func The function to apply a rest parameter to.
    * @param {number} [start=func.length-1] The start position of the rest parameter.
    * @returns {Function} Returns the new function.
    * @example
    *
    * var say = _.rest(function(what, names) {
    *   return what + ' ' + _.initial(names).join(', ') +
    *     (_.size(names) > 1 ? ', & ' : ) + _.last(names);
    * });
    *
    * say('hello', 'fred', 'barney', 'pebbles');
    * // => 'hello fred, barney, & pebbles'
    */
   function rest(func, start) {
     if (typeof func != 'function') {
       throw new TypeError(FUNC_ERROR_TEXT);
     }
     start = start === undefined ? start : toInteger(start);
     return baseRest(func, start);
   }
   /**
    * Creates a function that invokes `func` with the `this` binding of the
    * create function and an array of arguments much like
    * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
    *
    * **Note:** This method is based on the
    * [spread operator](https://mdn.io/spread_operator).
    *
    * @static
    * @memberOf _
    * @since 3.2.0
    * @category Function
    * @param {Function} func The function to spread arguments over.
    * @param {number} [start=0] The start position of the spread.
    * @returns {Function} Returns the new function.
    * @example
    *
    * var say = _.spread(function(who, what) {
    *   return who + ' says ' + what;
    * });
    *
    * say(['fred', 'hello']);
    * // => 'fred says hello'
    *
    * var numbers = Promise.all([
    *   Promise.resolve(40),
    *   Promise.resolve(36)
    * ]);
    *
    * numbers.then(_.spread(function(x, y) {
    *   return x + y;
    * }));
    * // => a Promise of 76
    */
   function spread(func, start) {
     if (typeof func != 'function') {
       throw new TypeError(FUNC_ERROR_TEXT);
     }
     start = start == null ? 0 : nativeMax(toInteger(start), 0);
     return baseRest(function(args) {
       var array = args[start],
           otherArgs = castSlice(args, 0, start);
       if (array) {
         arrayPush(otherArgs, array);
       }
       return apply(func, this, otherArgs);
     });
   }
   /**
    * Creates a throttled function that only invokes `func` at most once per
    * every `wait` milliseconds. The throttled function comes with a `cancel`
    * method to cancel delayed `func` invocations and a `flush` method to
    * immediately invoke them. Provide `options` to indicate whether `func`
    * should be invoked on the leading and/or trailing edge of the `wait`
    * timeout. The `func` is invoked with the last arguments provided to the
    * throttled function. Subsequent calls to the throttled function return the
    * result of the last `func` invocation.
    *
    * **Note:** If `leading` and `trailing` options are `true`, `func` is
    * invoked on the trailing edge of the timeout only if the throttled function
    * is invoked more than once during the `wait` timeout.
    *
    * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
    * until to the next tick, similar to `setTimeout` with a timeout of `0`.
    *
    * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
    * for details over the differences between `_.throttle` and `_.debounce`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Function
    * @param {Function} func The function to throttle.
    * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
    * @param {Object} [options={}] The options object.
    * @param {boolean} [options.leading=true]
    *  Specify invoking on the leading edge of the timeout.
    * @param {boolean} [options.trailing=true]
    *  Specify invoking on the trailing edge of the timeout.
    * @returns {Function} Returns the new throttled function.
    * @example
    *
    * // Avoid excessively updating the position while scrolling.
    * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
    *
    * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
    * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
    * jQuery(element).on('click', throttled);
    *
    * // Cancel the trailing throttled invocation.
    * jQuery(window).on('popstate', throttled.cancel);
    */
   function throttle(func, wait, options) {
     var leading = true,
         trailing = true;
     if (typeof func != 'function') {
       throw new TypeError(FUNC_ERROR_TEXT);
     }
     if (isObject(options)) {
       leading = 'leading' in options ? !!options.leading : leading;
       trailing = 'trailing' in options ? !!options.trailing : trailing;
     }
     return debounce(func, wait, {
       'leading': leading,
       'maxWait': wait,
       'trailing': trailing
     });
   }
   /**
    * Creates a function that accepts up to one argument, ignoring any
    * additional arguments.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Function
    * @param {Function} func The function to cap arguments for.
    * @returns {Function} Returns the new capped function.
    * @example
    *
    * _.map(['6', '8', '10'], _.unary(parseInt));
    * // => [6, 8, 10]
    */
   function unary(func) {
     return ary(func, 1);
   }
   /**
    * Creates a function that provides `value` to `wrapper` as its first
    * argument. Any additional arguments provided to the function are appended
    * to those provided to the `wrapper`. The wrapper is invoked with the `this`
    * binding of the created function.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Function
    * @param {*} value The value to wrap.
    * @param {Function} [wrapper=identity] The wrapper function.
    * @returns {Function} Returns the new function.
    * @example
    *
    * var p = _.wrap(_.escape, function(func, text) {
* return '

' + func(text) + '

';
    * });
    *
    * p('fred, barney, & pebbles');
* // => '

fred, barney, & pebbles

'
    */
   function wrap(value, wrapper) {
     return partial(castFunction(wrapper), value);
   }
   /*------------------------------------------------------------------------*/
   /**
    * Casts `value` as an array if it's not one.
    *
    * @static
    * @memberOf _
    * @since 4.4.0
    * @category Lang
    * @param {*} value The value to inspect.
    * @returns {Array} Returns the cast array.
    * @example
    *
    * _.castArray(1);
    * // => [1]
    *
    * _.castArray({ 'a': 1 });
    * // => [{ 'a': 1 }]
    *
    * _.castArray('abc');
    * // => ['abc']
    *
    * _.castArray(null);
    * // => [null]
    *
    * _.castArray(undefined);
    * // => [undefined]
    *
    * _.castArray();
    * // => []
    *
    * var array = [1, 2, 3];
    * console.log(_.castArray(array) === array);
    * // => true
    */
   function castArray() {
     if (!arguments.length) {
       return [];
     }
     var value = arguments[0];
     return isArray(value) ? value : [value];
   }
   /**
    * Creates a shallow clone of `value`.
    *
    * **Note:** This method is loosely based on the
    * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
    * and supports cloning arrays, array buffers, booleans, date objects, maps,
    * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
    * arrays. The own enumerable properties of `arguments` objects are cloned
    * as plain objects. An empty object is returned for uncloneable values such
    * as error objects, functions, DOM nodes, and WeakMaps.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to clone.
    * @returns {*} Returns the cloned value.
    * @see _.cloneDeep
    * @example
    *
    * var objects = [{ 'a': 1 }, { 'b': 2 }];
    *
    * var shallow = _.clone(objects);
    * console.log(shallow[0] === objects[0]);
    * // => true
    */
   function clone(value) {
     return baseClone(value, CLONE_SYMBOLS_FLAG);
   }
   /**
    * This method is like `_.clone` except that it accepts `customizer` which
    * is invoked to produce the cloned value. If `customizer` returns `undefined`,
    * cloning is handled by the method instead. The `customizer` is invoked with
    * up to four arguments; (value [, index|key, object, stack]).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to clone.
    * @param {Function} [customizer] The function to customize cloning.
    * @returns {*} Returns the cloned value.
    * @see _.cloneDeepWith
    * @example
    *
    * function customizer(value) {
    *   if (_.isElement(value)) {
    *     return value.cloneNode(false);
    *   }
    * }
    *
    * var el = _.cloneWith(document.body, customizer);
    *
    * console.log(el === document.body);
    * // => false
    * console.log(el.nodeName);
    * // => 'BODY'
    * console.log(el.childNodes.length);
    * // => 0
    */
   function cloneWith(value, customizer) {
     customizer = typeof customizer == 'function' ? customizer : undefined;
     return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
   }
   /**
    * This method is like `_.clone` except that it recursively clones `value`.
    *
    * @static
    * @memberOf _
    * @since 1.0.0
    * @category Lang
    * @param {*} value The value to recursively clone.
    * @returns {*} Returns the deep cloned value.
    * @see _.clone
    * @example
    *
    * var objects = [{ 'a': 1 }, { 'b': 2 }];
    *
    * var deep = _.cloneDeep(objects);
    * console.log(deep[0] === objects[0]);
    * // => false
    */
   function cloneDeep(value) {
     return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
   }
   /**
    * This method is like `_.cloneWith` except that it recursively clones `value`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to recursively clone.
    * @param {Function} [customizer] The function to customize cloning.
    * @returns {*} Returns the deep cloned value.
    * @see _.cloneWith
    * @example
    *
    * function customizer(value) {
    *   if (_.isElement(value)) {
    *     return value.cloneNode(true);
    *   }
    * }
    *
    * var el = _.cloneDeepWith(document.body, customizer);
    *
    * console.log(el === document.body);
    * // => false
    * console.log(el.nodeName);
    * // => 'BODY'
    * console.log(el.childNodes.length);
    * // => 20
    */
   function cloneDeepWith(value, customizer) {
     customizer = typeof customizer == 'function' ? customizer : undefined;
     return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
   }
   /**
    * Checks if `object` conforms to `source` by invoking the predicate
    * properties of `source` with the corresponding property values of `object`.
    *
    * **Note:** This method is equivalent to `_.conforms` when `source` is
    * partially applied.
    *
    * @static
    * @memberOf _
    * @since 4.14.0
    * @category Lang
    * @param {Object} object The object to inspect.
    * @param {Object} source The object of property predicates to conform to.
    * @returns {boolean} Returns `true` if `object` conforms, else `false`.
    * @example
    *
    * var object = { 'a': 1, 'b': 2 };
    *
    * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
    * // => true
    *
    * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
    * // => false
    */
   function conformsTo(object, source) {
     return source == null || baseConformsTo(object, source, keys(source));
   }
   /**
    * Performs a
    * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
    * comparison between two values to determine if they are equivalent.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
    * @example
    *
    * var object = { 'a': 1 };
    * var other = { 'a': 1 };
    *
    * _.eq(object, object);
    * // => true
    *
    * _.eq(object, other);
    * // => false
    *
    * _.eq('a', 'a');
    * // => true
    *
    * _.eq('a', Object('a'));
    * // => false
    *
    * _.eq(NaN, NaN);
    * // => true
    */
   function eq(value, other) {
     return value === other || (value !== value && other !== other);
   }
   /**
    * Checks if `value` is greater than `other`.
    *
    * @static
    * @memberOf _
    * @since 3.9.0
    * @category Lang
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @returns {boolean} Returns `true` if `value` is greater than `other`,
    *  else `false`.
    * @see _.lt
    * @example
    *
    * _.gt(3, 1);
    * // => true
    *
    * _.gt(3, 3);
    * // => false
    *
    * _.gt(1, 3);
    * // => false
    */
   var gt = createRelationalOperation(baseGt);
   /**
    * Checks if `value` is greater than or equal to `other`.
    *
    * @static
    * @memberOf _
    * @since 3.9.0
    * @category Lang
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @returns {boolean} Returns `true` if `value` is greater than or equal to
    *  `other`, else `false`.
    * @see _.lte
    * @example
    *
    * _.gte(3, 1);
    * // => true
    *
    * _.gte(3, 3);
    * // => true
    *
    * _.gte(1, 3);
    * // => false
    */
   var gte = createRelationalOperation(function(value, other) {
     return value >= other;
   });
   /**
    * Checks if `value` is likely an `arguments` object.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is an `arguments` object,
    *  else `false`.
    * @example
    *
    * _.isArguments(function() { return arguments; }());
    * // => true
    *
    * _.isArguments([1, 2, 3]);
    * // => false
    */
   var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
     return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
       !propertyIsEnumerable.call(value, 'callee');
   };
   /**
    * Checks if `value` is classified as an `Array` object.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is an array, else `false`.
    * @example
    *
    * _.isArray([1, 2, 3]);
    * // => true
    *
    * _.isArray(document.body.children);
    * // => false
    *
    * _.isArray('abc');
    * // => false
    *
    * _.isArray(_.noop);
    * // => false
    */
   var isArray = Array.isArray;
   /**
    * Checks if `value` is classified as an `ArrayBuffer` object.
    *
    * @static
    * @memberOf _
    * @since 4.3.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
    * @example
    *
    * _.isArrayBuffer(new ArrayBuffer(2));
    * // => true
    *
    * _.isArrayBuffer(new Array(2));
    * // => false
    */
   var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
   /**
    * Checks if `value` is array-like. A value is considered array-like if it's
    * not a function and has a `value.length` that's an integer greater than or
    * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
    * @example
    *
    * _.isArrayLike([1, 2, 3]);
    * // => true
    *
    * _.isArrayLike(document.body.children);
    * // => true
    *
    * _.isArrayLike('abc');
    * // => true
    *
    * _.isArrayLike(_.noop);
    * // => false
    */
   function isArrayLike(value) {
     return value != null && isLength(value.length) && !isFunction(value);
   }
   /**
    * This method is like `_.isArrayLike` except that it also checks if `value`
    * is an object.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is an array-like object,
    *  else `false`.
    * @example
    *
    * _.isArrayLikeObject([1, 2, 3]);
    * // => true
    *
    * _.isArrayLikeObject(document.body.children);
    * // => true
    *
    * _.isArrayLikeObject('abc');
    * // => false
    *
    * _.isArrayLikeObject(_.noop);
    * // => false
    */
   function isArrayLikeObject(value) {
     return isObjectLike(value) && isArrayLike(value);
   }
   /**
    * Checks if `value` is classified as a boolean primitive or object.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
    * @example
    *
    * _.isBoolean(false);
    * // => true
    *
    * _.isBoolean(null);
    * // => false
    */
   function isBoolean(value) {
     return value === true || value === false ||
       (isObjectLike(value) && baseGetTag(value) == boolTag);
   }
   /**
    * Checks if `value` is a buffer.
    *
    * @static
    * @memberOf _
    * @since 4.3.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
    * @example
    *
    * _.isBuffer(new Buffer(2));
    * // => true
    *
    * _.isBuffer(new Uint8Array(2));
    * // => false
    */
   var isBuffer = nativeIsBuffer || stubFalse;
   /**
    * Checks if `value` is classified as a `Date` object.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
    * @example
    *
    * _.isDate(new Date);
    * // => true
    *
    * _.isDate('Mon April 23 2012');
    * // => false
    */
   var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
   /**
    * Checks if `value` is likely a DOM element.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
    * @example
    *
    * _.isElement(document.body);
    * // => true
    *
    * _.isElement('<body>');
    * // => false
    */
   function isElement(value) {
     return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
   }
   /**
    * Checks if `value` is an empty object, collection, map, or set.
    *
    * Objects are considered empty if they have no own enumerable string keyed
    * properties.
    *
    * Array-like values such as `arguments` objects, arrays, buffers, strings, or
    * jQuery-like collections are considered empty if they have a `length` of `0`.
    * Similarly, maps and sets are considered empty if they have a `size` of `0`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is empty, else `false`.
    * @example
    *
    * _.isEmpty(null);
    * // => true
    *
    * _.isEmpty(true);
    * // => true
    *
    * _.isEmpty(1);
    * // => true
    *
    * _.isEmpty([1, 2, 3]);
    * // => false
    *
    * _.isEmpty({ 'a': 1 });
    * // => false
    */
   function isEmpty(value) {
     if (value == null) {
       return true;
     }
     if (isArrayLike(value) &&
         (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
           isBuffer(value) || isTypedArray(value) || isArguments(value))) {
       return !value.length;
     }
     var tag = getTag(value);
     if (tag == mapTag || tag == setTag) {
       return !value.size;
     }
     if (isPrototype(value)) {
       return !baseKeys(value).length;
     }
     for (var key in value) {
       if (hasOwnProperty.call(value, key)) {
         return false;
       }
     }
     return true;
   }
   /**
    * Performs a deep comparison between two values to determine if they are
    * equivalent.
    *
    * **Note:** This method supports comparing arrays, array buffers, booleans,
    * date objects, error objects, maps, numbers, `Object` objects, regexes,
    * sets, strings, symbols, and typed arrays. `Object` objects are compared
    * by their own, not inherited, enumerable properties. Functions and DOM
    * nodes are compared by strict equality, i.e. `===`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
    * @example
    *
    * var object = { 'a': 1 };
    * var other = { 'a': 1 };
    *
    * _.isEqual(object, other);
    * // => true
    *
    * object === other;
    * // => false
    */
   function isEqual(value, other) {
     return baseIsEqual(value, other);
   }
   /**
    * This method is like `_.isEqual` except that it accepts `customizer` which
    * is invoked to compare values. If `customizer` returns `undefined`, comparisons
    * are handled by the method instead. The `customizer` is invoked with up to
    * six arguments: (objValue, othValue [, index|key, object, other, stack]).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @param {Function} [customizer] The function to customize comparisons.
    * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
    * @example
    *
    * function isGreeting(value) {
    *   return /^h(?:i|ello)$/.test(value);
    * }
    *
    * function customizer(objValue, othValue) {
    *   if (isGreeting(objValue) && isGreeting(othValue)) {
    *     return true;
    *   }
    * }
    *
    * var array = ['hello', 'goodbye'];
    * var other = ['hi', 'goodbye'];
    *
    * _.isEqualWith(array, other, customizer);
    * // => true
    */
   function isEqualWith(value, other, customizer) {
     customizer = typeof customizer == 'function' ? customizer : undefined;
     var result = customizer ? customizer(value, other) : undefined;
     return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
   }
   /**
    * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
    * `SyntaxError`, `TypeError`, or `URIError` object.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
    * @example
    *
    * _.isError(new Error);
    * // => true
    *
    * _.isError(Error);
    * // => false
    */
   function isError(value) {
     if (!isObjectLike(value)) {
       return false;
     }
     var tag = baseGetTag(value);
     return tag == errorTag || tag == domExcTag ||
       (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
   }
   /**
    * Checks if `value` is a finite primitive number.
    *
    * **Note:** This method is based on
    * [`Number.isFinite`](https://mdn.io/Number/isFinite).
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
    * @example
    *
    * _.isFinite(3);
    * // => true
    *
    * _.isFinite(Number.MIN_VALUE);
    * // => true
    *
    * _.isFinite(Infinity);
    * // => false
    *
    * _.isFinite('3');
    * // => false
    */
   function isFinite(value) {
     return typeof value == 'number' && nativeIsFinite(value);
   }
   /**
    * Checks if `value` is classified as a `Function` object.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a function, else `false`.
    * @example
    *
    * _.isFunction(_);
    * // => true
    *
    * _.isFunction(/abc/);
    * // => false
    */
   function isFunction(value) {
     if (!isObject(value)) {
       return false;
     }
     // The use of `Object#toString` avoids issues with the `typeof` operator
     // in Safari 9 which returns 'object' for typed arrays and other constructors.
     var tag = baseGetTag(value);
     return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
   }
   /**
    * Checks if `value` is an integer.
    *
    * **Note:** This method is based on
    * [`Number.isInteger`](https://mdn.io/Number/isInteger).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
    * @example
    *
    * _.isInteger(3);
    * // => true
    *
    * _.isInteger(Number.MIN_VALUE);
    * // => false
    *
    * _.isInteger(Infinity);
    * // => false
    *
    * _.isInteger('3');
    * // => false
    */
   function isInteger(value) {
     return typeof value == 'number' && value == toInteger(value);
   }
   /**
    * Checks if `value` is a valid array-like length.
    *
    * **Note:** This method is loosely based on
    * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
    * @example
    *
    * _.isLength(3);
    * // => true
    *
    * _.isLength(Number.MIN_VALUE);
    * // => false
    *
    * _.isLength(Infinity);
    * // => false
    *
    * _.isLength('3');
    * // => false
    */
   function isLength(value) {
     return typeof value == 'number' &&
       value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
   }
   /**
    * Checks if `value` is the
    * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
    * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String()`)
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is an object, else `false`.
    * @example
    *
    * _.isObject({});
    * // => true
    *
    * _.isObject([1, 2, 3]);
    * // => true
    *
    * _.isObject(_.noop);
    * // => true
    *
    * _.isObject(null);
    * // => false
    */
   function isObject(value) {
     var type = typeof value;
     return value != null && (type == 'object' || type == 'function');
   }
   /**
    * Checks if `value` is object-like. A value is object-like if it's not `null`
    * and has a `typeof` result of "object".
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
    * @example
    *
    * _.isObjectLike({});
    * // => true
    *
    * _.isObjectLike([1, 2, 3]);
    * // => true
    *
    * _.isObjectLike(_.noop);
    * // => false
    *
    * _.isObjectLike(null);
    * // => false
    */
   function isObjectLike(value) {
     return value != null && typeof value == 'object';
   }
   /**
    * Checks if `value` is classified as a `Map` object.
    *
    * @static
    * @memberOf _
    * @since 4.3.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a map, else `false`.
    * @example
    *
    * _.isMap(new Map);
    * // => true
    *
    * _.isMap(new WeakMap);
    * // => false
    */
   var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
   /**
    * Performs a partial deep comparison between `object` and `source` to
    * determine if `object` contains equivalent property values.
    *
    * **Note:** This method is equivalent to `_.matches` when `source` is
    * partially applied.
    *
    * Partial comparisons will match empty array and empty object `source`
    * values against any array or object value, respectively. See `_.isEqual`
    * for a list of supported value comparisons.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Lang
    * @param {Object} object The object to inspect.
    * @param {Object} source The object of property values to match.
    * @returns {boolean} Returns `true` if `object` is a match, else `false`.
    * @example
    *
    * var object = { 'a': 1, 'b': 2 };
    *
    * _.isMatch(object, { 'b': 2 });
    * // => true
    *
    * _.isMatch(object, { 'b': 1 });
    * // => false
    */
   function isMatch(object, source) {
     return object === source || baseIsMatch(object, source, getMatchData(source));
   }
   /**
    * This method is like `_.isMatch` except that it accepts `customizer` which
    * is invoked to compare values. If `customizer` returns `undefined`, comparisons
    * are handled by the method instead. The `customizer` is invoked with five
    * arguments: (objValue, srcValue, index|key, object, source).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {Object} object The object to inspect.
    * @param {Object} source The object of property values to match.
    * @param {Function} [customizer] The function to customize comparisons.
    * @returns {boolean} Returns `true` if `object` is a match, else `false`.
    * @example
    *
    * function isGreeting(value) {
    *   return /^h(?:i|ello)$/.test(value);
    * }
    *
    * function customizer(objValue, srcValue) {
    *   if (isGreeting(objValue) && isGreeting(srcValue)) {
    *     return true;
    *   }
    * }
    *
    * var object = { 'greeting': 'hello' };
    * var source = { 'greeting': 'hi' };
    *
    * _.isMatchWith(object, source, customizer);
    * // => true
    */
   function isMatchWith(object, source, customizer) {
     customizer = typeof customizer == 'function' ? customizer : undefined;
     return baseIsMatch(object, source, getMatchData(source), customizer);
   }
   /**
    * Checks if `value` is `NaN`.
    *
    * **Note:** This method is based on
    * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
    * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
    * `undefined` and other non-number values.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
    * @example
    *
    * _.isNaN(NaN);
    * // => true
    *
    * _.isNaN(new Number(NaN));
    * // => true
    *
    * isNaN(undefined);
    * // => true
    *
    * _.isNaN(undefined);
    * // => false
    */
   function isNaN(value) {
     // An `NaN` primitive is the only value that is not equal to itself.
     // Perform the `toStringTag` check first to avoid errors with some
     // ActiveX objects in IE.
     return isNumber(value) && value != +value;
   }
   /**
    * Checks if `value` is a pristine native function.
    *
    * **Note:** This method can't reliably detect native functions in the presence
    * of the core-js package because core-js circumvents this kind of detection.
    * Despite multiple requests, the core-js maintainer has made it clear: any
    * attempt to fix the detection will be obstructed. As a result, we're left
    * with little choice but to throw an error. Unfortunately, this also affects
    * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
    * which rely on core-js.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a native function,
    *  else `false`.
    * @example
    *
    * _.isNative(Array.prototype.push);
    * // => true
    *
    * _.isNative(_);
    * // => false
    */
   function isNative(value) {
     if (isMaskable(value)) {
       throw new Error(CORE_ERROR_TEXT);
     }
     return baseIsNative(value);
   }
   /**
    * Checks if `value` is `null`.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
    * @example
    *
    * _.isNull(null);
    * // => true
    *
    * _.isNull(void 0);
    * // => false
    */
   function isNull(value) {
     return value === null;
   }
   /**
    * Checks if `value` is `null` or `undefined`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
    * @example
    *
    * _.isNil(null);
    * // => true
    *
    * _.isNil(void 0);
    * // => true
    *
    * _.isNil(NaN);
    * // => false
    */
   function isNil(value) {
     return value == null;
   }
   /**
    * Checks if `value` is classified as a `Number` primitive or object.
    *
    * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
    * classified as numbers, use the `_.isFinite` method.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a number, else `false`.
    * @example
    *
    * _.isNumber(3);
    * // => true
    *
    * _.isNumber(Number.MIN_VALUE);
    * // => true
    *
    * _.isNumber(Infinity);
    * // => true
    *
    * _.isNumber('3');
    * // => false
    */
   function isNumber(value) {
     return typeof value == 'number' ||
       (isObjectLike(value) && baseGetTag(value) == numberTag);
   }
   /**
    * Checks if `value` is a plain object, that is, an object created by the
    * `Object` constructor or one with a `Prototype` of `null`.
    *
    * @static
    * @memberOf _
    * @since 0.8.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    * }
    *
    * _.isPlainObject(new Foo);
    * // => false
    *
    * _.isPlainObject([1, 2, 3]);
    * // => false
    *
    * _.isPlainObject({ 'x': 0, 'y': 0 });
    * // => true
    *
    * _.isPlainObject(Object.create(null));
    * // => true
    */
   function isPlainObject(value) {
     if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
       return false;
     }
     var proto = getPrototype(value);
     if (proto === null) {
       return true;
     }
     var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
     return typeof Ctor == 'function' && Ctor instanceof Ctor &&
       funcToString.call(Ctor) == objectCtorString;
   }
   /**
    * Checks if `value` is classified as a `RegExp` object.
    *
    * @static
    * @memberOf _
    * @since 0.1.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
    * @example
    *
    * _.isRegExp(/abc/);
    * // => true
    *
    * _.isRegExp('/abc/');
    * // => false
    */
   var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
   /**
    * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
    * double precision number which isn't the result of a rounded unsafe integer.
    *
    * **Note:** This method is based on
    * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
    * @example
    *
    * _.isSafeInteger(3);
    * // => true
    *
    * _.isSafeInteger(Number.MIN_VALUE);
    * // => false
    *
    * _.isSafeInteger(Infinity);
    * // => false
    *
    * _.isSafeInteger('3');
    * // => false
    */
   function isSafeInteger(value) {
     return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
   }
   /**
    * Checks if `value` is classified as a `Set` object.
    *
    * @static
    * @memberOf _
    * @since 4.3.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a set, else `false`.
    * @example
    *
    * _.isSet(new Set);
    * // => true
    *
    * _.isSet(new WeakSet);
    * // => false
    */
   var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
   /**
    * Checks if `value` is classified as a `String` primitive or object.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a string, else `false`.
    * @example
    *
    * _.isString('abc');
    * // => true
    *
    * _.isString(1);
    * // => false
    */
   function isString(value) {
     return typeof value == 'string' ||
       (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
   }
   /**
    * Checks if `value` is classified as a `Symbol` primitive or object.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
    * @example
    *
    * _.isSymbol(Symbol.iterator);
    * // => true
    *
    * _.isSymbol('abc');
    * // => false
    */
   function isSymbol(value) {
     return typeof value == 'symbol' ||
       (isObjectLike(value) && baseGetTag(value) == symbolTag);
   }
   /**
    * Checks if `value` is classified as a typed array.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
    * @example
    *
    * _.isTypedArray(new Uint8Array);
    * // => true
    *
    * _.isTypedArray([]);
    * // => false
    */
   var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
   /**
    * Checks if `value` is `undefined`.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
    * @example
    *
    * _.isUndefined(void 0);
    * // => true
    *
    * _.isUndefined(null);
    * // => false
    */
   function isUndefined(value) {
     return value === undefined;
   }
   /**
    * Checks if `value` is classified as a `WeakMap` object.
    *
    * @static
    * @memberOf _
    * @since 4.3.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
    * @example
    *
    * _.isWeakMap(new WeakMap);
    * // => true
    *
    * _.isWeakMap(new Map);
    * // => false
    */
   function isWeakMap(value) {
     return isObjectLike(value) && getTag(value) == weakMapTag;
   }
   /**
    * Checks if `value` is classified as a `WeakSet` object.
    *
    * @static
    * @memberOf _
    * @since 4.3.0
    * @category Lang
    * @param {*} value The value to check.
    * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
    * @example
    *
    * _.isWeakSet(new WeakSet);
    * // => true
    *
    * _.isWeakSet(new Set);
    * // => false
    */
   function isWeakSet(value) {
     return isObjectLike(value) && baseGetTag(value) == weakSetTag;
   }
   /**
    * Checks if `value` is less than `other`.
    *
    * @static
    * @memberOf _
    * @since 3.9.0
    * @category Lang
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @returns {boolean} Returns `true` if `value` is less than `other`,
    *  else `false`.
    * @see _.gt
    * @example
    *
    * _.lt(1, 3);
    * // => true
    *
    * _.lt(3, 3);
    * // => false
    *
    * _.lt(3, 1);
    * // => false
    */
   var lt = createRelationalOperation(baseLt);
   /**
    * Checks if `value` is less than or equal to `other`.
    *
    * @static
    * @memberOf _
    * @since 3.9.0
    * @category Lang
    * @param {*} value The value to compare.
    * @param {*} other The other value to compare.
    * @returns {boolean} Returns `true` if `value` is less than or equal to
    *  `other`, else `false`.
    * @see _.gte
    * @example
    *
    * _.lte(1, 3);
    * // => true
    *
    * _.lte(3, 3);
    * // => true
    *
    * _.lte(3, 1);
    * // => false
    */
   var lte = createRelationalOperation(function(value, other) {
     return value <= other;
   });
   /**
    * Converts `value` to an array.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Lang
    * @param {*} value The value to convert.
    * @returns {Array} Returns the converted array.
    * @example
    *
    * _.toArray({ 'a': 1, 'b': 2 });
    * // => [1, 2]
    *
    * _.toArray('abc');
    * // => ['a', 'b', 'c']
    *
    * _.toArray(1);
    * // => []
    *
    * _.toArray(null);
    * // => []
    */
   function toArray(value) {
     if (!value) {
       return [];
     }
     if (isArrayLike(value)) {
       return isString(value) ? stringToArray(value) : copyArray(value);
     }
     if (symIterator && value[symIterator]) {
       return iteratorToArray(value[symIterator]());
     }
     var tag = getTag(value),
         func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
     return func(value);
   }
   /**
    * Converts `value` to a finite number.
    *
    * @static
    * @memberOf _
    * @since 4.12.0
    * @category Lang
    * @param {*} value The value to convert.
    * @returns {number} Returns the converted number.
    * @example
    *
    * _.toFinite(3.2);
    * // => 3.2
    *
    * _.toFinite(Number.MIN_VALUE);
    * // => 5e-324
    *
    * _.toFinite(Infinity);
    * // => 1.7976931348623157e+308
    *
    * _.toFinite('3.2');
    * // => 3.2
    */
   function toFinite(value) {
     if (!value) {
       return value === 0 ? value : 0;
     }
     value = toNumber(value);
     if (value === INFINITY || value === -INFINITY) {
       var sign = (value < 0 ? -1 : 1);
       return sign * MAX_INTEGER;
     }
     return value === value ? value : 0;
   }
   /**
    * Converts `value` to an integer.
    *
    * **Note:** This method is loosely based on
    * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to convert.
    * @returns {number} Returns the converted integer.
    * @example
    *
    * _.toInteger(3.2);
    * // => 3
    *
    * _.toInteger(Number.MIN_VALUE);
    * // => 0
    *
    * _.toInteger(Infinity);
    * // => 1.7976931348623157e+308
    *
    * _.toInteger('3.2');
    * // => 3
    */
   function toInteger(value) {
     var result = toFinite(value),
         remainder = result % 1;
     return result === result ? (remainder ? result - remainder : result) : 0;
   }
   /**
    * Converts `value` to an integer suitable for use as the length of an
    * array-like object.
    *
    * **Note:** This method is based on
    * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to convert.
    * @returns {number} Returns the converted integer.
    * @example
    *
    * _.toLength(3.2);
    * // => 3
    *
    * _.toLength(Number.MIN_VALUE);
    * // => 0
    *
    * _.toLength(Infinity);
    * // => 4294967295
    *
    * _.toLength('3.2');
    * // => 3
    */
   function toLength(value) {
     return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
   }
   /**
    * Converts `value` to a number.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to process.
    * @returns {number} Returns the number.
    * @example
    *
    * _.toNumber(3.2);
    * // => 3.2
    *
    * _.toNumber(Number.MIN_VALUE);
    * // => 5e-324
    *
    * _.toNumber(Infinity);
    * // => Infinity
    *
    * _.toNumber('3.2');
    * // => 3.2
    */
   function toNumber(value) {
     if (typeof value == 'number') {
       return value;
     }
     if (isSymbol(value)) {
       return NAN;
     }
     if (isObject(value)) {
       var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
       value = isObject(other) ? (other + ) : other;
     }
     if (typeof value != 'string') {
       return value === 0 ? value : +value;
     }
     value = value.replace(reTrim, );
     var isBinary = reIsBinary.test(value);
     return (isBinary || reIsOctal.test(value))
       ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
       : (reIsBadHex.test(value) ? NAN : +value);
   }
   /**
    * Converts `value` to a plain object flattening inherited enumerable string
    * keyed properties of `value` to own properties of the plain object.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Lang
    * @param {*} value The value to convert.
    * @returns {Object} Returns the converted plain object.
    * @example
    *
    * function Foo() {
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.assign({ 'a': 1 }, new Foo);
    * // => { 'a': 1, 'b': 2 }
    *
    * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
    * // => { 'a': 1, 'b': 2, 'c': 3 }
    */
   function toPlainObject(value) {
     return copyObject(value, keysIn(value));
   }
   /**
    * Converts `value` to a safe integer. A safe integer can be compared and
    * represented correctly.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to convert.
    * @returns {number} Returns the converted integer.
    * @example
    *
    * _.toSafeInteger(3.2);
    * // => 3
    *
    * _.toSafeInteger(Number.MIN_VALUE);
    * // => 0
    *
    * _.toSafeInteger(Infinity);
    * // => 9007199254740991
    *
    * _.toSafeInteger('3.2');
    * // => 3
    */
   function toSafeInteger(value) {
     return value
       ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
       : (value === 0 ? value : 0);
   }
   /**
    * Converts `value` to a string. An empty string is returned for `null`
    * and `undefined` values. The sign of `-0` is preserved.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Lang
    * @param {*} value The value to convert.
    * @returns {string} Returns the converted string.
    * @example
    *
    * _.toString(null);
    * // => 
    *
    * _.toString(-0);
    * // => '-0'
    *
    * _.toString([1, 2, 3]);
    * // => '1,2,3'
    */
   function toString(value) {
     return value == null ?  : baseToString(value);
   }
   /*------------------------------------------------------------------------*/
   /**
    * Assigns own enumerable string keyed properties of source objects to the
    * destination object. Source objects are applied from left to right.
    * Subsequent sources overwrite property assignments of previous sources.
    *
    * **Note:** This method mutates `object` and is loosely based on
    * [`Object.assign`](https://mdn.io/Object/assign).
    *
    * @static
    * @memberOf _
    * @since 0.10.0
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} [sources] The source objects.
    * @returns {Object} Returns `object`.
    * @see _.assignIn
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    * }
    *
    * function Bar() {
    *   this.c = 3;
    * }
    *
    * Foo.prototype.b = 2;
    * Bar.prototype.d = 4;
    *
    * _.assign({ 'a': 0 }, new Foo, new Bar);
    * // => { 'a': 1, 'c': 3 }
    */
   var assign = createAssigner(function(object, source) {
     if (isPrototype(source) || isArrayLike(source)) {
       copyObject(source, keys(source), object);
       return;
     }
     for (var key in source) {
       if (hasOwnProperty.call(source, key)) {
         assignValue(object, key, source[key]);
       }
     }
   });
   /**
    * This method is like `_.assign` except that it iterates over own and
    * inherited source properties.
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @alias extend
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} [sources] The source objects.
    * @returns {Object} Returns `object`.
    * @see _.assign
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    * }
    *
    * function Bar() {
    *   this.c = 3;
    * }
    *
    * Foo.prototype.b = 2;
    * Bar.prototype.d = 4;
    *
    * _.assignIn({ 'a': 0 }, new Foo, new Bar);
    * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
    */
   var assignIn = createAssigner(function(object, source) {
     copyObject(source, keysIn(source), object);
   });
   /**
    * This method is like `_.assignIn` except that it accepts `customizer`
    * which is invoked to produce the assigned values. If `customizer` returns
    * `undefined`, assignment is handled by the method instead. The `customizer`
    * is invoked with five arguments: (objValue, srcValue, key, object, source).
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @alias extendWith
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} sources The source objects.
    * @param {Function} [customizer] The function to customize assigned values.
    * @returns {Object} Returns `object`.
    * @see _.assignWith
    * @example
    *
    * function customizer(objValue, srcValue) {
    *   return _.isUndefined(objValue) ? srcValue : objValue;
    * }
    *
    * var defaults = _.partialRight(_.assignInWith, customizer);
    *
    * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
    * // => { 'a': 1, 'b': 2 }
    */
   var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
     copyObject(source, keysIn(source), object, customizer);
   });
   /**
    * This method is like `_.assign` except that it accepts `customizer`
    * which is invoked to produce the assigned values. If `customizer` returns
    * `undefined`, assignment is handled by the method instead. The `customizer`
    * is invoked with five arguments: (objValue, srcValue, key, object, source).
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} sources The source objects.
    * @param {Function} [customizer] The function to customize assigned values.
    * @returns {Object} Returns `object`.
    * @see _.assignInWith
    * @example
    *
    * function customizer(objValue, srcValue) {
    *   return _.isUndefined(objValue) ? srcValue : objValue;
    * }
    *
    * var defaults = _.partialRight(_.assignWith, customizer);
    *
    * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
    * // => { 'a': 1, 'b': 2 }
    */
   var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
     copyObject(source, keys(source), object, customizer);
   });
   /**
    * Creates an array of values corresponding to `paths` of `object`.
    *
    * @static
    * @memberOf _
    * @since 1.0.0
    * @category Object
    * @param {Object} object The object to iterate over.
    * @param {...(string|string[])} [paths] The property paths to pick.
    * @returns {Array} Returns the picked values.
    * @example
    *
    * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
    *
    * _.at(object, ['a[0].b.c', 'a[1]']);
    * // => [3, 4]
    */
   var at = flatRest(baseAt);
   /**
    * Creates an object that inherits from the `prototype` object. If a
    * `properties` object is given, its own enumerable string keyed properties
    * are assigned to the created object.
    *
    * @static
    * @memberOf _
    * @since 2.3.0
    * @category Object
    * @param {Object} prototype The object to inherit from.
    * @param {Object} [properties] The properties to assign to the object.
    * @returns {Object} Returns the new object.
    * @example
    *
    * function Shape() {
    *   this.x = 0;
    *   this.y = 0;
    * }
    *
    * function Circle() {
    *   Shape.call(this);
    * }
    *
    * Circle.prototype = _.create(Shape.prototype, {
    *   'constructor': Circle
    * });
    *
    * var circle = new Circle;
    * circle instanceof Circle;
    * // => true
    *
    * circle instanceof Shape;
    * // => true
    */
   function create(prototype, properties) {
     var result = baseCreate(prototype);
     return properties == null ? result : baseAssign(result, properties);
   }
   /**
    * Assigns own and inherited enumerable string keyed properties of source
    * objects to the destination object for all destination properties that
    * resolve to `undefined`. Source objects are applied from left to right.
    * Once a property is set, additional values of the same property are ignored.
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} [sources] The source objects.
    * @returns {Object} Returns `object`.
    * @see _.defaultsDeep
    * @example
    *
    * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
    * // => { 'a': 1, 'b': 2 }
    */
   var defaults = baseRest(function(object, sources) {
     object = Object(object);
     var index = -1;
     var length = sources.length;
     var guard = length > 2 ? sources[2] : undefined;
     if (guard && isIterateeCall(sources[0], sources[1], guard)) {
       length = 1;
     }
     while (++index < length) {
       var source = sources[index];
       var props = keysIn(source);
       var propsIndex = -1;
       var propsLength = props.length;
       while (++propsIndex < propsLength) {
         var key = props[propsIndex];
         var value = object[key];
         if (value === undefined ||
             (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {
           object[key] = source[key];
         }
       }
     }
     return object;
   });
   /**
    * This method is like `_.defaults` except that it recursively assigns
    * default properties.
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 3.10.0
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} [sources] The source objects.
    * @returns {Object} Returns `object`.
    * @see _.defaults
    * @example
    *
    * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
    * // => { 'a': { 'b': 2, 'c': 3 } }
    */
   var defaultsDeep = baseRest(function(args) {
     args.push(undefined, customDefaultsMerge);
     return apply(mergeWith, undefined, args);
   });
   /**
    * This method is like `_.find` except that it returns the key of the first
    * element `predicate` returns truthy for instead of the element itself.
    *
    * @static
    * @memberOf _
    * @since 1.1.0
    * @category Object
    * @param {Object} object The object to inspect.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @returns {string|undefined} Returns the key of the matched element,
    *  else `undefined`.
    * @example
    *
    * var users = {
    *   'barney':  { 'age': 36, 'active': true },
    *   'fred':    { 'age': 40, 'active': false },
    *   'pebbles': { 'age': 1,  'active': true }
    * };
    *
    * _.findKey(users, function(o) { return o.age < 40; });
    * // => 'barney' (iteration order is not guaranteed)
    *
    * // The `_.matches` iteratee shorthand.
    * _.findKey(users, { 'age': 1, 'active': true });
    * // => 'pebbles'
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.findKey(users, ['active', false]);
    * // => 'fred'
    *
    * // The `_.property` iteratee shorthand.
    * _.findKey(users, 'active');
    * // => 'barney'
    */
   function findKey(object, predicate) {
     return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
   }
   /**
    * This method is like `_.findKey` except that it iterates over elements of
    * a collection in the opposite order.
    *
    * @static
    * @memberOf _
    * @since 2.0.0
    * @category Object
    * @param {Object} object The object to inspect.
    * @param {Function} [predicate=_.identity] The function invoked per iteration.
    * @returns {string|undefined} Returns the key of the matched element,
    *  else `undefined`.
    * @example
    *
    * var users = {
    *   'barney':  { 'age': 36, 'active': true },
    *   'fred':    { 'age': 40, 'active': false },
    *   'pebbles': { 'age': 1,  'active': true }
    * };
    *
    * _.findLastKey(users, function(o) { return o.age < 40; });
    * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
    *
    * // The `_.matches` iteratee shorthand.
    * _.findLastKey(users, { 'age': 36, 'active': true });
    * // => 'barney'
    *
    * // The `_.matchesProperty` iteratee shorthand.
    * _.findLastKey(users, ['active', false]);
    * // => 'fred'
    *
    * // The `_.property` iteratee shorthand.
    * _.findLastKey(users, 'active');
    * // => 'pebbles'
    */
   function findLastKey(object, predicate) {
     return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
   }
   /**
    * Iterates over own and inherited enumerable string keyed properties of an
    * object and invokes `iteratee` for each property. The iteratee is invoked
    * with three arguments: (value, key, object). Iteratee functions may exit
    * iteration early by explicitly returning `false`.
    *
    * @static
    * @memberOf _
    * @since 0.3.0
    * @category Object
    * @param {Object} object The object to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Object} Returns `object`.
    * @see _.forInRight
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.forIn(new Foo, function(value, key) {
    *   console.log(key);
    * });
    * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
    */
   function forIn(object, iteratee) {
     return object == null
       ? object
       : baseFor(object, getIteratee(iteratee, 3), keysIn);
   }
   /**
    * This method is like `_.forIn` except that it iterates over properties of
    * `object` in the opposite order.
    *
    * @static
    * @memberOf _
    * @since 2.0.0
    * @category Object
    * @param {Object} object The object to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Object} Returns `object`.
    * @see _.forIn
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.forInRight(new Foo, function(value, key) {
    *   console.log(key);
    * });
    * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
    */
   function forInRight(object, iteratee) {
     return object == null
       ? object
       : baseForRight(object, getIteratee(iteratee, 3), keysIn);
   }
   /**
    * Iterates over own enumerable string keyed properties of an object and
    * invokes `iteratee` for each property. The iteratee is invoked with three
    * arguments: (value, key, object). Iteratee functions may exit iteration
    * early by explicitly returning `false`.
    *
    * @static
    * @memberOf _
    * @since 0.3.0
    * @category Object
    * @param {Object} object The object to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Object} Returns `object`.
    * @see _.forOwnRight
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.forOwn(new Foo, function(value, key) {
    *   console.log(key);
    * });
    * // => Logs 'a' then 'b' (iteration order is not guaranteed).
    */
   function forOwn(object, iteratee) {
     return object && baseForOwn(object, getIteratee(iteratee, 3));
   }
   /**
    * This method is like `_.forOwn` except that it iterates over properties of
    * `object` in the opposite order.
    *
    * @static
    * @memberOf _
    * @since 2.0.0
    * @category Object
    * @param {Object} object The object to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Object} Returns `object`.
    * @see _.forOwn
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.forOwnRight(new Foo, function(value, key) {
    *   console.log(key);
    * });
    * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
    */
   function forOwnRight(object, iteratee) {
     return object && baseForOwnRight(object, getIteratee(iteratee, 3));
   }
   /**
    * Creates an array of function property names from own enumerable properties
    * of `object`.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The object to inspect.
    * @returns {Array} Returns the function names.
    * @see _.functionsIn
    * @example
    *
    * function Foo() {
    *   this.a = _.constant('a');
    *   this.b = _.constant('b');
    * }
    *
    * Foo.prototype.c = _.constant('c');
    *
    * _.functions(new Foo);
    * // => ['a', 'b']
    */
   function functions(object) {
     return object == null ? [] : baseFunctions(object, keys(object));
   }
   /**
    * Creates an array of function property names from own and inherited
    * enumerable properties of `object`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Object
    * @param {Object} object The object to inspect.
    * @returns {Array} Returns the function names.
    * @see _.functions
    * @example
    *
    * function Foo() {
    *   this.a = _.constant('a');
    *   this.b = _.constant('b');
    * }
    *
    * Foo.prototype.c = _.constant('c');
    *
    * _.functionsIn(new Foo);
    * // => ['a', 'b', 'c']
    */
   function functionsIn(object) {
     return object == null ? [] : baseFunctions(object, keysIn(object));
   }
   /**
    * Gets the value at `path` of `object`. If the resolved value is
    * `undefined`, the `defaultValue` is returned in its place.
    *
    * @static
    * @memberOf _
    * @since 3.7.0
    * @category Object
    * @param {Object} object The object to query.
    * @param {Array|string} path The path of the property to get.
    * @param {*} [defaultValue] The value returned for `undefined` resolved values.
    * @returns {*} Returns the resolved value.
    * @example
    *
    * var object = { 'a': [{ 'b': { 'c': 3 } }] };
    *
    * _.get(object, 'a[0].b.c');
    * // => 3
    *
    * _.get(object, ['a', '0', 'b', 'c']);
    * // => 3
    *
    * _.get(object, 'a.b.c', 'default');
    * // => 'default'
    */
   function get(object, path, defaultValue) {
     var result = object == null ? undefined : baseGet(object, path);
     return result === undefined ? defaultValue : result;
   }
   /**
    * Checks if `path` is a direct property of `object`.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The object to query.
    * @param {Array|string} path The path to check.
    * @returns {boolean} Returns `true` if `path` exists, else `false`.
    * @example
    *
    * var object = { 'a': { 'b': 2 } };
    * var other = _.create({ 'a': _.create({ 'b': 2 }) });
    *
    * _.has(object, 'a');
    * // => true
    *
    * _.has(object, 'a.b');
    * // => true
    *
    * _.has(object, ['a', 'b']);
    * // => true
    *
    * _.has(other, 'a');
    * // => false
    */
   function has(object, path) {
     return object != null && hasPath(object, path, baseHas);
   }
   /**
    * Checks if `path` is a direct or inherited property of `object`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Object
    * @param {Object} object The object to query.
    * @param {Array|string} path The path to check.
    * @returns {boolean} Returns `true` if `path` exists, else `false`.
    * @example
    *
    * var object = _.create({ 'a': _.create({ 'b': 2 }) });
    *
    * _.hasIn(object, 'a');
    * // => true
    *
    * _.hasIn(object, 'a.b');
    * // => true
    *
    * _.hasIn(object, ['a', 'b']);
    * // => true
    *
    * _.hasIn(object, 'b');
    * // => false
    */
   function hasIn(object, path) {
     return object != null && hasPath(object, path, baseHasIn);
   }
   /**
    * Creates an object composed of the inverted keys and values of `object`.
    * If `object` contains duplicate values, subsequent values overwrite
    * property assignments of previous values.
    *
    * @static
    * @memberOf _
    * @since 0.7.0
    * @category Object
    * @param {Object} object The object to invert.
    * @returns {Object} Returns the new inverted object.
    * @example
    *
    * var object = { 'a': 1, 'b': 2, 'c': 1 };
    *
    * _.invert(object);
    * // => { '1': 'c', '2': 'b' }
    */
   var invert = createInverter(function(result, value, key) {
     if (value != null &&
         typeof value.toString != 'function') {
       value = nativeObjectToString.call(value);
     }
     result[value] = key;
   }, constant(identity));
   /**
    * This method is like `_.invert` except that the inverted object is generated
    * from the results of running each element of `object` thru `iteratee`. The
    * corresponding inverted value of each inverted key is an array of keys
    * responsible for generating the inverted value. The iteratee is invoked
    * with one argument: (value).
    *
    * @static
    * @memberOf _
    * @since 4.1.0
    * @category Object
    * @param {Object} object The object to invert.
    * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
    * @returns {Object} Returns the new inverted object.
    * @example
    *
    * var object = { 'a': 1, 'b': 2, 'c': 1 };
    *
    * _.invertBy(object);
    * // => { '1': ['a', 'c'], '2': ['b'] }
    *
    * _.invertBy(object, function(value) {
    *   return 'group' + value;
    * });
    * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
    */
   var invertBy = createInverter(function(result, value, key) {
     if (value != null &&
         typeof value.toString != 'function') {
       value = nativeObjectToString.call(value);
     }
     if (hasOwnProperty.call(result, value)) {
       result[value].push(key);
     } else {
       result[value] = [key];
     }
   }, getIteratee);
   /**
    * Invokes the method at `path` of `object`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Object
    * @param {Object} object The object to query.
    * @param {Array|string} path The path of the method to invoke.
    * @param {...*} [args] The arguments to invoke the method with.
    * @returns {*} Returns the result of the invoked method.
    * @example
    *
    * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
    *
    * _.invoke(object, 'a[0].b.c.slice', 1, 3);
    * // => [2, 3]
    */
   var invoke = baseRest(baseInvoke);
   /**
    * Creates an array of the own enumerable property names of `object`.
    *
    * **Note:** Non-object values are coerced to objects. See the
    * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
    * for more details.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of property names.
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.keys(new Foo);
    * // => ['a', 'b'] (iteration order is not guaranteed)
    *
    * _.keys('hi');
    * // => ['0', '1']
    */
   function keys(object) {
     return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
   }
   /**
    * Creates an array of the own and inherited enumerable property names of `object`.
    *
    * **Note:** Non-object values are coerced to objects.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Object
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of property names.
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.keysIn(new Foo);
    * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
    */
   function keysIn(object) {
     return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
   }
   /**
    * The opposite of `_.mapValues`; this method creates an object with the
    * same values as `object` and keys generated by running each own enumerable
    * string keyed property of `object` thru `iteratee`. The iteratee is invoked
    * with three arguments: (value, key, object).
    *
    * @static
    * @memberOf _
    * @since 3.8.0
    * @category Object
    * @param {Object} object The object to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Object} Returns the new mapped object.
    * @see _.mapValues
    * @example
    *
    * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
    *   return key + value;
    * });
    * // => { 'a1': 1, 'b2': 2 }
    */
   function mapKeys(object, iteratee) {
     var result = {};
     iteratee = getIteratee(iteratee, 3);
     baseForOwn(object, function(value, key, object) {
       baseAssignValue(result, iteratee(value, key, object), value);
     });
     return result;
   }
   /**
    * Creates an object with the same keys as `object` and values generated
    * by running each own enumerable string keyed property of `object` thru
    * `iteratee`. The iteratee is invoked with three arguments:
    * (value, key, object).
    *
    * @static
    * @memberOf _
    * @since 2.4.0
    * @category Object
    * @param {Object} object The object to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @returns {Object} Returns the new mapped object.
    * @see _.mapKeys
    * @example
    *
    * var users = {
    *   'fred':    { 'user': 'fred',    'age': 40 },
    *   'pebbles': { 'user': 'pebbles', 'age': 1 }
    * };
    *
    * _.mapValues(users, function(o) { return o.age; });
    * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
    *
    * // The `_.property` iteratee shorthand.
    * _.mapValues(users, 'age');
    * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
    */
   function mapValues(object, iteratee) {
     var result = {};
     iteratee = getIteratee(iteratee, 3);
     baseForOwn(object, function(value, key, object) {
       baseAssignValue(result, key, iteratee(value, key, object));
     });
     return result;
   }
   /**
    * This method is like `_.assign` except that it recursively merges own and
    * inherited enumerable string keyed properties of source objects into the
    * destination object. Source properties that resolve to `undefined` are
    * skipped if a destination value exists. Array and plain object properties
    * are merged recursively. Other objects and value types are overridden by
    * assignment. Source objects are applied from left to right. Subsequent
    * sources overwrite property assignments of previous sources.
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 0.5.0
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} [sources] The source objects.
    * @returns {Object} Returns `object`.
    * @example
    *
    * var object = {
    *   'a': [{ 'b': 2 }, { 'd': 4 }]
    * };
    *
    * var other = {
    *   'a': [{ 'c': 3 }, { 'e': 5 }]
    * };
    *
    * _.merge(object, other);
    * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
    */
   var merge = createAssigner(function(object, source, srcIndex) {
     baseMerge(object, source, srcIndex);
   });
   /**
    * This method is like `_.merge` except that it accepts `customizer` which
    * is invoked to produce the merged values of the destination and source
    * properties. If `customizer` returns `undefined`, merging is handled by the
    * method instead. The `customizer` is invoked with six arguments:
    * (objValue, srcValue, key, object, source, stack).
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Object
    * @param {Object} object The destination object.
    * @param {...Object} sources The source objects.
    * @param {Function} customizer The function to customize assigned values.
    * @returns {Object} Returns `object`.
    * @example
    *
    * function customizer(objValue, srcValue) {
    *   if (_.isArray(objValue)) {
    *     return objValue.concat(srcValue);
    *   }
    * }
    *
    * var object = { 'a': [1], 'b': [2] };
    * var other = { 'a': [3], 'b': [4] };
    *
    * _.mergeWith(object, other, customizer);
    * // => { 'a': [1, 3], 'b': [2, 4] }
    */
   var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
     baseMerge(object, source, srcIndex, customizer);
   });
   /**
    * The opposite of `_.pick`; this method creates an object composed of the
    * own and inherited enumerable property paths of `object` that are not omitted.
    *
    * **Note:** This method is considerably slower than `_.pick`.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The source object.
    * @param {...(string|string[])} [paths] The property paths to omit.
    * @returns {Object} Returns the new object.
    * @example
    *
    * var object = { 'a': 1, 'b': '2', 'c': 3 };
    *
    * _.omit(object, ['a', 'c']);
    * // => { 'b': '2' }
    */
   var omit = flatRest(function(object, paths) {
     var result = {};
     if (object == null) {
       return result;
     }
     var isDeep = false;
     paths = arrayMap(paths, function(path) {
       path = castPath(path, object);
       isDeep || (isDeep = path.length > 1);
       return path;
     });
     copyObject(object, getAllKeysIn(object), result);
     if (isDeep) {
       result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
     }
     var length = paths.length;
     while (length--) {
       baseUnset(result, paths[length]);
     }
     return result;
   });
   /**
    * The opposite of `_.pickBy`; this method creates an object composed of
    * the own and inherited enumerable string keyed properties of `object` that
    * `predicate` doesn't return truthy for. The predicate is invoked with two
    * arguments: (value, key).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Object
    * @param {Object} object The source object.
    * @param {Function} [predicate=_.identity] The function invoked per property.
    * @returns {Object} Returns the new object.
    * @example
    *
    * var object = { 'a': 1, 'b': '2', 'c': 3 };
    *
    * _.omitBy(object, _.isNumber);
    * // => { 'b': '2' }
    */
   function omitBy(object, predicate) {
     return pickBy(object, negate(getIteratee(predicate)));
   }
   /**
    * Creates an object composed of the picked `object` properties.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The source object.
    * @param {...(string|string[])} [paths] The property paths to pick.
    * @returns {Object} Returns the new object.
    * @example
    *
    * var object = { 'a': 1, 'b': '2', 'c': 3 };
    *
    * _.pick(object, ['a', 'c']);
    * // => { 'a': 1, 'c': 3 }
    */
   var pick = flatRest(function(object, paths) {
     return object == null ? {} : basePick(object, paths);
   });
   /**
    * Creates an object composed of the `object` properties `predicate` returns
    * truthy for. The predicate is invoked with two arguments: (value, key).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Object
    * @param {Object} object The source object.
    * @param {Function} [predicate=_.identity] The function invoked per property.
    * @returns {Object} Returns the new object.
    * @example
    *
    * var object = { 'a': 1, 'b': '2', 'c': 3 };
    *
    * _.pickBy(object, _.isNumber);
    * // => { 'a': 1, 'c': 3 }
    */
   function pickBy(object, predicate) {
     if (object == null) {
       return {};
     }
     var props = arrayMap(getAllKeysIn(object), function(prop) {
       return [prop];
     });
     predicate = getIteratee(predicate);
     return basePickBy(object, props, function(value, path) {
       return predicate(value, path[0]);
     });
   }
   /**
    * This method is like `_.get` except that if the resolved value is a
    * function it's invoked with the `this` binding of its parent object and
    * its result is returned.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The object to query.
    * @param {Array|string} path The path of the property to resolve.
    * @param {*} [defaultValue] The value returned for `undefined` resolved values.
    * @returns {*} Returns the resolved value.
    * @example
    *
    * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
    *
    * _.result(object, 'a[0].b.c1');
    * // => 3
    *
    * _.result(object, 'a[0].b.c2');
    * // => 4
    *
    * _.result(object, 'a[0].b.c3', 'default');
    * // => 'default'
    *
    * _.result(object, 'a[0].b.c3', _.constant('default'));
    * // => 'default'
    */
   function result(object, path, defaultValue) {
     path = castPath(path, object);
     var index = -1,
         length = path.length;
     // Ensure the loop is entered when path is empty.
     if (!length) {
       length = 1;
       object = undefined;
     }
     while (++index < length) {
       var value = object == null ? undefined : object[toKey(path[index])];
       if (value === undefined) {
         index = length;
         value = defaultValue;
       }
       object = isFunction(value) ? value.call(object) : value;
     }
     return object;
   }
   /**
    * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
    * it's created. Arrays are created for missing index properties while objects
    * are created for all other missing properties. Use `_.setWith` to customize
    * `path` creation.
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 3.7.0
    * @category Object
    * @param {Object} object The object to modify.
    * @param {Array|string} path The path of the property to set.
    * @param {*} value The value to set.
    * @returns {Object} Returns `object`.
    * @example
    *
    * var object = { 'a': [{ 'b': { 'c': 3 } }] };
    *
    * _.set(object, 'a[0].b.c', 4);
    * console.log(object.a[0].b.c);
    * // => 4
    *
    * _.set(object, ['x', '0', 'y', 'z'], 5);
    * console.log(object.x[0].y.z);
    * // => 5
    */
   function set(object, path, value) {
     return object == null ? object : baseSet(object, path, value);
   }
   /**
    * This method is like `_.set` except that it accepts `customizer` which is
    * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
    * path creation is handled by the method instead. The `customizer` is invoked
    * with three arguments: (nsValue, key, nsObject).
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Object
    * @param {Object} object The object to modify.
    * @param {Array|string} path The path of the property to set.
    * @param {*} value The value to set.
    * @param {Function} [customizer] The function to customize assigned values.
    * @returns {Object} Returns `object`.
    * @example
    *
    * var object = {};
    *
    * _.setWith(object, '[0][1]', 'a', Object);
    * // => { '0': { '1': 'a' } }
    */
   function setWith(object, path, value, customizer) {
     customizer = typeof customizer == 'function' ? customizer : undefined;
     return object == null ? object : baseSet(object, path, value, customizer);
   }
   /**
    * Creates an array of own enumerable string keyed-value pairs for `object`
    * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
    * entries are returned.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @alias entries
    * @category Object
    * @param {Object} object The object to query.
    * @returns {Array} Returns the key-value pairs.
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.toPairs(new Foo);
    * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
    */
   var toPairs = createToPairs(keys);
   /**
    * Creates an array of own and inherited enumerable string keyed-value pairs
    * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
    * or set, its entries are returned.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @alias entriesIn
    * @category Object
    * @param {Object} object The object to query.
    * @returns {Array} Returns the key-value pairs.
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.toPairsIn(new Foo);
    * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
    */
   var toPairsIn = createToPairs(keysIn);
   /**
    * An alternative to `_.reduce`; this method transforms `object` to a new
    * `accumulator` object which is the result of running each of its own
    * enumerable string keyed properties thru `iteratee`, with each invocation
    * potentially mutating the `accumulator` object. If `accumulator` is not
    * provided, a new object with the same `Prototype` will be used. The
    * iteratee is invoked with four arguments: (accumulator, value, key, object).
    * Iteratee functions may exit iteration early by explicitly returning `false`.
    *
    * @static
    * @memberOf _
    * @since 1.3.0
    * @category Object
    * @param {Object} object The object to iterate over.
    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
    * @param {*} [accumulator] The custom accumulator value.
    * @returns {*} Returns the accumulated value.
    * @example
    *
    * _.transform([2, 3, 4], function(result, n) {
    *   result.push(n *= n);
    *   return n % 2 == 0;
    * }, []);
    * // => [4, 9]
    *
    * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
    *   (result[value] || (result[value] = [])).push(key);
    * }, {});
    * // => { '1': ['a', 'c'], '2': ['b'] }
    */
   function transform(object, iteratee, accumulator) {
     var isArr = isArray(object),
         isArrLike = isArr || isBuffer(object) || isTypedArray(object);
     iteratee = getIteratee(iteratee, 4);
     if (accumulator == null) {
       var Ctor = object && object.constructor;
       if (isArrLike) {
         accumulator = isArr ? new Ctor : [];
       }
       else if (isObject(object)) {
         accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
       }
       else {
         accumulator = {};
       }
     }
     (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
       return iteratee(accumulator, value, index, object);
     });
     return accumulator;
   }
   /**
    * Removes the property at `path` of `object`.
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Object
    * @param {Object} object The object to modify.
    * @param {Array|string} path The path of the property to unset.
    * @returns {boolean} Returns `true` if the property is deleted, else `false`.
    * @example
    *
    * var object = { 'a': [{ 'b': { 'c': 7 } }] };
    * _.unset(object, 'a[0].b.c');
    * // => true
    *
    * console.log(object);
    * // => { 'a': [{ 'b': {} }] };
    *
    * _.unset(object, ['a', '0', 'b', 'c']);
    * // => true
    *
    * console.log(object);
    * // => { 'a': [{ 'b': {} }] };
    */
   function unset(object, path) {
     return object == null ? true : baseUnset(object, path);
   }
   /**
    * This method is like `_.set` except that accepts `updater` to produce the
    * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
    * is invoked with one argument: (value).
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 4.6.0
    * @category Object
    * @param {Object} object The object to modify.
    * @param {Array|string} path The path of the property to set.
    * @param {Function} updater The function to produce the updated value.
    * @returns {Object} Returns `object`.
    * @example
    *
    * var object = { 'a': [{ 'b': { 'c': 3 } }] };
    *
    * _.update(object, 'a[0].b.c', function(n) { return n * n; });
    * console.log(object.a[0].b.c);
    * // => 9
    *
    * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
    * console.log(object.x[0].y.z);
    * // => 0
    */
   function update(object, path, updater) {
     return object == null ? object : baseUpdate(object, path, castFunction(updater));
   }
   /**
    * This method is like `_.update` except that it accepts `customizer` which is
    * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
    * path creation is handled by the method instead. The `customizer` is invoked
    * with three arguments: (nsValue, key, nsObject).
    *
    * **Note:** This method mutates `object`.
    *
    * @static
    * @memberOf _
    * @since 4.6.0
    * @category Object
    * @param {Object} object The object to modify.
    * @param {Array|string} path The path of the property to set.
    * @param {Function} updater The function to produce the updated value.
    * @param {Function} [customizer] The function to customize assigned values.
    * @returns {Object} Returns `object`.
    * @example
    *
    * var object = {};
    *
    * _.updateWith(object, '[0][1]', _.constant('a'), Object);
    * // => { '0': { '1': 'a' } }
    */
   function updateWith(object, path, updater, customizer) {
     customizer = typeof customizer == 'function' ? customizer : undefined;
     return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
   }
   /**
    * Creates an array of the own enumerable string keyed property values of `object`.
    *
    * **Note:** Non-object values are coerced to objects.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category Object
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of property values.
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.values(new Foo);
    * // => [1, 2] (iteration order is not guaranteed)
    *
    * _.values('hi');
    * // => ['h', 'i']
    */
   function values(object) {
     return object == null ? [] : baseValues(object, keys(object));
   }
   /**
    * Creates an array of the own and inherited enumerable string keyed property
    * values of `object`.
    *
    * **Note:** Non-object values are coerced to objects.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category Object
    * @param {Object} object The object to query.
    * @returns {Array} Returns the array of property values.
    * @example
    *
    * function Foo() {
    *   this.a = 1;
    *   this.b = 2;
    * }
    *
    * Foo.prototype.c = 3;
    *
    * _.valuesIn(new Foo);
    * // => [1, 2, 3] (iteration order is not guaranteed)
    */
   function valuesIn(object) {
     return object == null ? [] : baseValues(object, keysIn(object));
   }
   /*------------------------------------------------------------------------*/
   /**
    * Clamps `number` within the inclusive `lower` and `upper` bounds.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category Number
    * @param {number} number The number to clamp.
    * @param {number} [lower] The lower bound.
    * @param {number} upper The upper bound.
    * @returns {number} Returns the clamped number.
    * @example
    *
    * _.clamp(-10, -5, 5);
    * // => -5
    *
    * _.clamp(10, -5, 5);
    * // => 5
    */
   function clamp(number, lower, upper) {
     if (upper === undefined) {
       upper = lower;
       lower = undefined;
     }
     if (upper !== undefined) {
       upper = toNumber(upper);
       upper = upper === upper ? upper : 0;
     }
     if (lower !== undefined) {
       lower = toNumber(lower);
       lower = lower === lower ? lower : 0;
     }
     return baseClamp(toNumber(number), lower, upper);
   }
   /**
    * Checks if `n` is between `start` and up to, but not including, `end`. If
    * `end` is not specified, it's set to `start` with `start` then set to `0`.
    * If `start` is greater than `end` the params are swapped to support
    * negative ranges.
    *
    * @static
    * @memberOf _
    * @since 3.3.0
    * @category Number
    * @param {number} number The number to check.
    * @param {number} [start=0] The start of the range.
    * @param {number} end The end of the range.
    * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
    * @see _.range, _.rangeRight
    * @example
    *
    * _.inRange(3, 2, 4);
    * // => true
    *
    * _.inRange(4, 8);
    * // => true
    *
    * _.inRange(4, 2);
    * // => false
    *
    * _.inRange(2, 2);
    * // => false
    *
    * _.inRange(1.2, 2);
    * // => true
    *
    * _.inRange(5.2, 4);
    * // => false
    *
    * _.inRange(-3, -2, -6);
    * // => true
    */
   function inRange(number, start, end) {
     start = toFinite(start);
     if (end === undefined) {
       end = start;
       start = 0;
     } else {
       end = toFinite(end);
     }
     number = toNumber(number);
     return baseInRange(number, start, end);
   }
   /**
    * Produces a random number between the inclusive `lower` and `upper` bounds.
    * If only one argument is provided a number between `0` and the given number
    * is returned. If `floating` is `true`, or either `lower` or `upper` are
    * floats, a floating-point number is returned instead of an integer.
    *
    * **Note:** JavaScript follows the IEEE-754 standard for resolving
    * floating-point values which can produce unexpected results.
    *
    * @static
    * @memberOf _
    * @since 0.7.0
    * @category Number
    * @param {number} [lower=0] The lower bound.
    * @param {number} [upper=1] The upper bound.
    * @param {boolean} [floating] Specify returning a floating-point number.
    * @returns {number} Returns the random number.
    * @example
    *
    * _.random(0, 5);
    * // => an integer between 0 and 5
    *
    * _.random(5);
    * // => also an integer between 0 and 5
    *
    * _.random(5, true);
    * // => a floating-point number between 0 and 5
    *
    * _.random(1.2, 5.2);
    * // => a floating-point number between 1.2 and 5.2
    */
   function random(lower, upper, floating) {
     if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
       upper = floating = undefined;
     }
     if (floating === undefined) {
       if (typeof upper == 'boolean') {
         floating = upper;
         upper = undefined;
       }
       else if (typeof lower == 'boolean') {
         floating = lower;
         lower = undefined;
       }
     }
     if (lower === undefined && upper === undefined) {
       lower = 0;
       upper = 1;
     }
     else {
       lower = toFinite(lower);
       if (upper === undefined) {
         upper = lower;
         lower = 0;
       } else {
         upper = toFinite(upper);
       }
     }
     if (lower > upper) {
       var temp = lower;
       lower = upper;
       upper = temp;
     }
     if (floating || lower % 1 || upper % 1) {
       var rand = nativeRandom();
       return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + ).length - 1)))), upper);
     }
     return baseRandom(lower, upper);
   }
   /*------------------------------------------------------------------------*/
   /**
    * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category String
    * @param {string} [string=] The string to convert.
    * @returns {string} Returns the camel cased string.
    * @example
    *
    * _.camelCase('Foo Bar');
    * // => 'fooBar'
    *
    * _.camelCase('--foo-bar--');
    * // => 'fooBar'
    *
    * _.camelCase('__FOO_BAR__');
    * // => 'fooBar'
    */
   var camelCase = createCompounder(function(result, word, index) {
     word = word.toLowerCase();
     return result + (index ? capitalize(word) : word);
   });
   /**
    * Converts the first character of `string` to upper case and the remaining
    * to lower case.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category String
    * @param {string} [string=] The string to capitalize.
    * @returns {string} Returns the capitalized string.
    * @example
    *
    * _.capitalize('FRED');
    * // => 'Fred'
    */
   function capitalize(string) {
     return upperFirst(toString(string).toLowerCase());
   }
   /**
    * Deburrs `string` by converting
    * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
    * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
    * letters to basic Latin letters and removing
    * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category String
    * @param {string} [string=] The string to deburr.
    * @returns {string} Returns the deburred string.
    * @example
    *
    * _.deburr('déjà vu');
    * // => 'deja vu'
    */
   function deburr(string) {
     string = toString(string);
     return string && string.replace(reLatin, deburrLetter).replace(reComboMark, );
   }
   /**
    * Checks if `string` ends with the given target string.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category String
    * @param {string} [string=] The string to inspect.
    * @param {string} [target] The string to search for.
    * @param {number} [position=string.length] The position to search up to.
    * @returns {boolean} Returns `true` if `string` ends with `target`,
    *  else `false`.
    * @example
    *
    * _.endsWith('abc', 'c');
    * // => true
    *
    * _.endsWith('abc', 'b');
    * // => false
    *
    * _.endsWith('abc', 'b', 2);
    * // => true
    */
   function endsWith(string, target, position) {
     string = toString(string);
     target = baseToString(target);
     var length = string.length;
     position = position === undefined
       ? length
       : baseClamp(toInteger(position), 0, length);
     var end = position;
     position -= target.length;
     return position >= 0 && string.slice(position, end) == target;
   }
   /**
    * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
    * corresponding HTML entities.
    *
    * **Note:** No other characters are escaped. To escape additional
    * characters use a third-party library like [_he_](https://mths.be/he).
    *
    * Though the ">" character is escaped for symmetry, characters like
    * ">" and "/" don't need escaping in HTML and have no special meaning
    * unless they're part of a tag or unquoted attribute value. See
    * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
    * (under "semi-related fun fact") for more details.
    *
    * When working with HTML you should always
    * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
    * XSS vectors.
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category String
    * @param {string} [string=] The string to escape.
    * @returns {string} Returns the escaped string.
    * @example
    *
    * _.escape('fred, barney, & pebbles');
    * // => 'fred, barney, & pebbles'
    */
   function escape(string) {
     string = toString(string);
     return (string && reHasUnescapedHtml.test(string))
       ? string.replace(reUnescapedHtml, escapeHtmlChar)
       : string;
   }
   /**
    * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
    * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category String
    * @param {string} [string=] The string to escape.
    * @returns {string} Returns the escaped string.
    * @example
    *
    * _.escapeRegExp('[lodash](https://lodash.com/)');
    * // => '\[lodash\]\(https://lodash\.com/\)'
    */
   function escapeRegExp(string) {
     string = toString(string);
     return (string && reHasRegExpChar.test(string))
       ? string.replace(reRegExpChar, '\\$&')
       : string;
   }
   /**
    * Converts `string` to
    * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category String
    * @param {string} [string=] The string to convert.
    * @returns {string} Returns the kebab cased string.
    * @example
    *
    * _.kebabCase('Foo Bar');
    * // => 'foo-bar'
    *
    * _.kebabCase('fooBar');
    * // => 'foo-bar'
    *
    * _.kebabCase('__FOO_BAR__');
    * // => 'foo-bar'
    */
   var kebabCase = createCompounder(function(result, word, index) {
     return result + (index ? '-' : ) + word.toLowerCase();
   });
   /**
    * Converts `string`, as space separated words, to lower case.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category String
    * @param {string} [string=] The string to convert.
    * @returns {string} Returns the lower cased string.
    * @example
    *
    * _.lowerCase('--Foo-Bar--');
    * // => 'foo bar'
    *
    * _.lowerCase('fooBar');
    * // => 'foo bar'
    *
    * _.lowerCase('__FOO_BAR__');
    * // => 'foo bar'
    */
   var lowerCase = createCompounder(function(result, word, index) {
     return result + (index ? ' ' : ) + word.toLowerCase();
   });
   /**
    * Converts the first character of `string` to lower case.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category String
    * @param {string} [string=] The string to convert.
    * @returns {string} Returns the converted string.
    * @example
    *
    * _.lowerFirst('Fred');
    * // => 'fred'
    *
    * _.lowerFirst('FRED');
    * // => 'fRED'
    */
   var lowerFirst = createCaseFirst('toLowerCase');
   /**
    * Pads `string` on the left and right sides if it's shorter than `length`.
    * Padding characters are truncated if they can't be evenly divided by `length`.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category String
    * @param {string} [string=] The string to pad.
    * @param {number} [length=0] The padding length.
    * @param {string} [chars=' '] The string used as padding.
    * @returns {string} Returns the padded string.
    * @example
    *
    * _.pad('abc', 8);
    * // => '  abc   '
    *
    * _.pad('abc', 8, '_-');
    * // => '_-abc_-_'
    *
    * _.pad('abc', 3);
    * // => 'abc'
    */
   function pad(string, length, chars) {
     string = toString(string);
     length = toInteger(length);
     var strLength = length ? stringSize(string) : 0;
     if (!length || strLength >= length) {
       return string;
     }
     var mid = (length - strLength) / 2;
     return (
       createPadding(nativeFloor(mid), chars) +
       string +
       createPadding(nativeCeil(mid), chars)
     );
   }
   /**
    * Pads `string` on the right side if it's shorter than `length`. Padding
    * characters are truncated if they exceed `length`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category String
    * @param {string} [string=] The string to pad.
    * @param {number} [length=0] The padding length.
    * @param {string} [chars=' '] The string used as padding.
    * @returns {string} Returns the padded string.
    * @example
    *
    * _.padEnd('abc', 6);
    * // => 'abc   '
    *
    * _.padEnd('abc', 6, '_-');
    * // => 'abc_-_'
    *
    * _.padEnd('abc', 3);
    * // => 'abc'
    */
   function padEnd(string, length, chars) {
     string = toString(string);
     length = toInteger(length);
     var strLength = length ? stringSize(string) : 0;
     return (length && strLength < length)
       ? (string + createPadding(length - strLength, chars))
       : string;
   }
   /**
    * Pads `string` on the left side if it's shorter than `length`. Padding
    * characters are truncated if they exceed `length`.
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category String
    * @param {string} [string=] The string to pad.
    * @param {number} [length=0] The padding length.
    * @param {string} [chars=' '] The string used as padding.
    * @returns {string} Returns the padded string.
    * @example
    *
    * _.padStart('abc', 6);
    * // => '   abc'
    *
    * _.padStart('abc', 6, '_-');
    * // => '_-_abc'
    *
    * _.padStart('abc', 3);
    * // => 'abc'
    */
   function padStart(string, length, chars) {
     string = toString(string);
     length = toInteger(length);
     var strLength = length ? stringSize(string) : 0;
     return (length && strLength < length)
       ? (createPadding(length - strLength, chars) + string)
       : string;
   }
   /**
    * Converts `string` to an integer of the specified radix. If `radix` is
    * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
    * hexadecimal, in which case a `radix` of `16` is used.
    *
    * **Note:** This method aligns with the
    * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
    *
    * @static
    * @memberOf _
    * @since 1.1.0
    * @category String
    * @param {string} string The string to convert.
    * @param {number} [radix=10] The radix to interpret `value` by.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {number} Returns the converted integer.
    * @example
    *
    * _.parseInt('08');
    * // => 8
    *
    * _.map(['6', '08', '10'], _.parseInt);
    * // => [6, 8, 10]
    */
   function parseInt(string, radix, guard) {
     if (guard || radix == null) {
       radix = 0;
     } else if (radix) {
       radix = +radix;
     }
     return nativeParseInt(toString(string).replace(reTrimStart, ), radix || 0);
   }
   /**
    * Repeats the given string `n` times.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category String
    * @param {string} [string=] The string to repeat.
    * @param {number} [n=1] The number of times to repeat the string.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {string} Returns the repeated string.
    * @example
    *
    * _.repeat('*', 3);
    * // => '***'
    *
    * _.repeat('abc', 2);
    * // => 'abcabc'
    *
    * _.repeat('abc', 0);
    * // => 
    */
   function repeat(string, n, guard) {
     if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
       n = 1;
     } else {
       n = toInteger(n);
     }
     return baseRepeat(toString(string), n);
   }
   /**
    * Replaces matches for `pattern` in `string` with `replacement`.
    *
    * **Note:** This method is based on
    * [`String#replace`](https://mdn.io/String/replace).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category String
    * @param {string} [string=] The string to modify.
    * @param {RegExp|string} pattern The pattern to replace.
    * @param {Function|string} replacement The match replacement.
    * @returns {string} Returns the modified string.
    * @example
    *
    * _.replace('Hi Fred', 'Fred', 'Barney');
    * // => 'Hi Barney'
    */
   function replace() {
     var args = arguments,
         string = toString(args[0]);
     return args.length < 3 ? string : string.replace(args[1], args[2]);
   }
   /**
    * Converts `string` to
    * [snake case](https://en.wikipedia.org/wiki/Snake_case).
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category String
    * @param {string} [string=] The string to convert.
    * @returns {string} Returns the snake cased string.
    * @example
    *
    * _.snakeCase('Foo Bar');
    * // => 'foo_bar'
    *
    * _.snakeCase('fooBar');
    * // => 'foo_bar'
    *
    * _.snakeCase('--FOO-BAR--');
    * // => 'foo_bar'
    */
   var snakeCase = createCompounder(function(result, word, index) {
     return result + (index ? '_' : ) + word.toLowerCase();
   });
   /**
    * Splits `string` by `separator`.
    *
    * **Note:** This method is based on
    * [`String#split`](https://mdn.io/String/split).
    *
    * @static
    * @memberOf _
    * @since 4.0.0
    * @category String
    * @param {string} [string=] The string to split.
    * @param {RegExp|string} separator The separator pattern to split by.
    * @param {number} [limit] The length to truncate results to.
    * @returns {Array} Returns the string segments.
    * @example
    *
    * _.split('a-b-c', '-', 2);
    * // => ['a', 'b']
    */
   function split(string, separator, limit) {
     if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
       separator = limit = undefined;
     }
     limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
     if (!limit) {
       return [];
     }
     string = toString(string);
     if (string && (
           typeof separator == 'string' ||
           (separator != null && !isRegExp(separator))
         )) {
       separator = baseToString(separator);
       if (!separator && hasUnicode(string)) {
         return castSlice(stringToArray(string), 0, limit);
       }
     }
     return string.split(separator, limit);
   }
   /**
    * Converts `string` to
    * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
    *
    * @static
    * @memberOf _
    * @since 3.1.0
    * @category String
    * @param {string} [string=] The string to convert.
    * @returns {string} Returns the start cased string.
    * @example
    *
    * _.startCase('--foo-bar--');
    * // => 'Foo Bar'
    *
    * _.startCase('fooBar');
    * // => 'Foo Bar'
    *
    * _.startCase('__FOO_BAR__');
    * // => 'FOO BAR'
    */
   var startCase = createCompounder(function(result, word, index) {
     return result + (index ? ' ' : ) + upperFirst(word);
   });
   /**
    * Checks if `string` starts with the given target string.
    *
    * @static
    * @memberOf _
    * @since 3.0.0
    * @category String
    * @param {string} [string=] The string to inspect.
    * @param {string} [target] The string to search for.
    * @param {number} [position=0] The position to search from.
    * @returns {boolean} Returns `true` if `string` starts with `target`,
    *  else `false`.
    * @example
    *
    * _.startsWith('abc', 'a');
    * // => true
    *
    * _.startsWith('abc', 'b');
    * // => false
    *
    * _.startsWith('abc', 'b', 1);
    * // => true
    */
   function startsWith(string, target, position) {
     string = toString(string);
     position = position == null
       ? 0
       : baseClamp(toInteger(position), 0, string.length);
     target = baseToString(target);
     return string.slice(position, position + target.length) == target;
   }
   /**
    * Creates a compiled template function that can interpolate data properties
    * in "interpolate" delimiters, HTML-escape interpolated data properties in
    * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
    * properties may be accessed as free variables in the template. If a setting
    * object is given, it takes precedence over `_.templateSettings` values.
    *
    * **Note:** In the development build `_.template` utilizes
    * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
    * for easier debugging.
    *
    * For more information on precompiling templates see
    * [lodash's custom builds documentation](https://lodash.com/custom-builds).
    *
    * For more information on Chrome extension sandboxes see
    * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
    *
    * @static
    * @since 0.1.0
    * @memberOf _
    * @category String
    * @param {string} [string=] The template string.
    * @param {Object} [options={}] The options object.
    * @param {RegExp} [options.escape=_.templateSettings.escape]
    *  The HTML "escape" delimiter.
    * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
    *  The "evaluate" delimiter.
    * @param {Object} [options.imports=_.templateSettings.imports]
    *  An object to import into the template as free variables.
    * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
    *  The "interpolate" delimiter.
    * @param {string} [options.sourceURL='lodash.templateSources[n]']
    *  The sourceURL of the compiled template.
    * @param {string} [options.variable='obj']
    *  The data object variable name.
    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
    * @returns {Function} Returns the compiled template function.
    * @example
    *
    * // Use the "interpolate" delimiter to create a compiled template.
    * var compiled = _.template('hello <%= user %>!');
    * compiled({ 'user': 'fred' });
    * // => 'hello fred!'
    *
    * // Use the HTML "escape" delimiter to escape data property values.
    * var compiled = _.template('<%- value %>');
    * compiled({ 'value': '<script>' });
    * // => '<script>'
    *
    * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
* var compiled = _.template('<% _.forEach(users, function(user) { %>
  • <%- user %>
  • <% }); %>');
        * compiled({ 'users': ['fred', 'barney'] });
    
    * // => '
  • fred
  • barney
  • '
        *
        * // Use the internal `print` function in "evaluate" delimiters.
        * var compiled = _.template('<% print("hello " + user); %>!');
        * compiled({ 'user': 'barney' });
        * // => 'hello barney!'
        *
        * // Use the ES template literal delimiter as an "interpolate" delimiter.
        * // Disable support by replacing the "interpolate" delimiter.
        * var compiled = _.template('hello ${ user }!');
        * compiled({ 'user': 'pebbles' });
        * // => 'hello pebbles!'
        *
        * // Use backslashes to treat delimiters as plain text.
        * var compiled = _.template('<%= "\\<%- value %\\>" %>');
        * compiled({ 'value': 'ignored' });
        * // => '<%- value %>'
        *
        * // Use the `imports` option to import `jQuery` as `jq`.
    
    * var text = '<% jq.each(users, function(user) { %>
  • <%- user %>
  • <% }); %>';
        * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
        * compiled({ 'users': ['fred', 'barney'] });
    
    * // => '
  • fred
  • barney
  • '
        *
        * // Use the `sourceURL` option to specify a custom sourceURL for the template.
        * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
        * compiled(data);
        * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
        *
        * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
        * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
        * compiled.source;
        * // => function(data) {
        * //   var __t, __p = ;
        * //   __p += 'hi ' + ((__t = ( data.user )) == null ?  : __t) + '!';
        * //   return __p;
        * // }
        *
        * // Use custom template delimiters.
        * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
        * var compiled = _.template('hello Template:User!');
        * compiled({ 'user': 'mustache' });
        * // => 'hello mustache!'
        *
        * // Use the `source` property to inline compiled templates for meaningful
        * // line numbers in error messages and stack traces.
        * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
        *   var JST = {\
        *     "main": ' + _.template(mainText).source + '\
        *   };\
        * ');
        */
       function template(string, options, guard) {
         // Based on John Resig's `tmpl` implementation
         // (http://ejohn.org/blog/javascript-micro-templating/)
         // and Laura Doktorova's doT.js (https://github.com/olado/doT).
         var settings = lodash.templateSettings;
    
         if (guard && isIterateeCall(string, options, guard)) {
           options = undefined;
         }
         string = toString(string);
         options = assignInWith({}, options, settings, customDefaultsAssignIn);
    
         var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
             importsKeys = keys(imports),
             importsValues = baseValues(imports, importsKeys);
    
         var isEscaping,
             isEvaluating,
             index = 0,
             interpolate = options.interpolate || reNoMatch,
             source = "__p += '";
    
         // Compile the regexp to match each delimiter.
         var reDelimiters = RegExp(
           (options.escape || reNoMatch).source + '|' +
           interpolate.source + '|' +
           (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
           (options.evaluate || reNoMatch).source + '|$'
         , 'g');
    
         // Use a sourceURL for easier debugging.
         // The sourceURL gets injected into the source that's eval-ed, so be careful
         // with lookup (in case of e.g. prototype pollution), and strip newlines if any.
         // A newline wouldn't be a valid sourceURL anyway, and it'd enable code injection.
         var sourceURL = '//# sourceURL=' +
           (hasOwnProperty.call(options, 'sourceURL')
             ? (options.sourceURL + ).replace(/[\r\n]/g, ' ')
             : ('lodash.templateSources[' + (++templateCounter) + ']')
           ) + '\n';
    
         string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
           interpolateValue || (interpolateValue = esTemplateValue);
    
           // Escape characters that can't be included in string literals.
           source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
    
           // Replace delimiters with snippets.
           if (escapeValue) {
             isEscaping = true;
             source += "' +\n__e(" + escapeValue + ") +\n'";
           }
           if (evaluateValue) {
             isEvaluating = true;
             source += "';\n" + evaluateValue + ";\n__p += '";
           }
           if (interpolateValue) {
             source += "' +\n((__t = (" + interpolateValue + ")) == null ?  : __t) +\n'";
           }
           index = offset + match.length;
    
           // The JS engine embedded in Adobe products needs `match` returned in
           // order to produce the correct `offset` value.
           return match;
         });
    
         source += "';\n";
    
         // If `variable` is not specified wrap a with-statement around the generated
         // code to add the data object to the top of the scope chain.
         // Like with sourceURL, we take care to not check the option's prototype,
         // as this configuration is a code injection vector.
         var variable = hasOwnProperty.call(options, 'variable') && options.variable;
         if (!variable) {
           source = 'with (obj) {\n' + source + '\n}\n';
         }
         // Cleanup code by stripping empty strings.
         source = (isEvaluating ? source.replace(reEmptyStringLeading, ) : source)
           .replace(reEmptyStringMiddle, '$1')
           .replace(reEmptyStringTrailing, '$1;');
    
         // Frame code as the function body.
         source = 'function(' + (variable || 'obj') + ') {\n' +
           (variable
             ? 
             : 'obj || (obj = {});\n'
           ) +
           "var __t, __p = " +
           (isEscaping
              ? ', __e = _.escape'
              : 
           ) +
           (isEvaluating
             ? ', __j = Array.prototype.join;\n' +
               "function print() { __p += __j.call(arguments, ) }\n"
             : ';\n'
           ) +
           source +
           'return __p\n}';
    
         var result = attempt(function() {
           return Function(importsKeys, sourceURL + 'return ' + source)
             .apply(undefined, importsValues);
         });
    
         // Provide the compiled function's source by its `toString` method or
         // the `source` property as a convenience for inlining compiled templates.
         result.source = source;
         if (isError(result)) {
           throw result;
         }
         return result;
       }
    
       /**
        * Converts `string`, as a whole, to lower case just like
        * [String#toLowerCase](https://mdn.io/toLowerCase).
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category String
        * @param {string} [string=] The string to convert.
        * @returns {string} Returns the lower cased string.
        * @example
        *
        * _.toLower('--Foo-Bar--');
        * // => '--foo-bar--'
        *
        * _.toLower('fooBar');
        * // => 'foobar'
        *
        * _.toLower('__FOO_BAR__');
        * // => '__foo_bar__'
        */
       function toLower(value) {
         return toString(value).toLowerCase();
       }
    
       /**
        * Converts `string`, as a whole, to upper case just like
        * [String#toUpperCase](https://mdn.io/toUpperCase).
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category String
        * @param {string} [string=] The string to convert.
        * @returns {string} Returns the upper cased string.
        * @example
        *
        * _.toUpper('--foo-bar--');
        * // => '--FOO-BAR--'
        *
        * _.toUpper('fooBar');
        * // => 'FOOBAR'
        *
        * _.toUpper('__foo_bar__');
        * // => '__FOO_BAR__'
        */
       function toUpper(value) {
         return toString(value).toUpperCase();
       }
    
       /**
        * Removes leading and trailing whitespace or specified characters from `string`.
        *
        * @static
        * @memberOf _
        * @since 3.0.0
        * @category String
        * @param {string} [string=] The string to trim.
        * @param {string} [chars=whitespace] The characters to trim.
        * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
        * @returns {string} Returns the trimmed string.
        * @example
        *
        * _.trim('  abc  ');
        * // => 'abc'
        *
        * _.trim('-_-abc-_-', '_-');
        * // => 'abc'
        *
        * _.map(['  foo  ', '  bar  '], _.trim);
        * // => ['foo', 'bar']
        */
       function trim(string, chars, guard) {
         string = toString(string);
         if (string && (guard || chars === undefined)) {
           return string.replace(reTrim, );
         }
         if (!string || !(chars = baseToString(chars))) {
           return string;
         }
         var strSymbols = stringToArray(string),
             chrSymbols = stringToArray(chars),
             start = charsStartIndex(strSymbols, chrSymbols),
             end = charsEndIndex(strSymbols, chrSymbols) + 1;
    
         return castSlice(strSymbols, start, end).join();
       }
    
       /**
        * Removes trailing whitespace or specified characters from `string`.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category String
        * @param {string} [string=] The string to trim.
        * @param {string} [chars=whitespace] The characters to trim.
        * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
        * @returns {string} Returns the trimmed string.
        * @example
        *
        * _.trimEnd('  abc  ');
        * // => '  abc'
        *
        * _.trimEnd('-_-abc-_-', '_-');
        * // => '-_-abc'
        */
       function trimEnd(string, chars, guard) {
         string = toString(string);
         if (string && (guard || chars === undefined)) {
           return string.replace(reTrimEnd, );
         }
         if (!string || !(chars = baseToString(chars))) {
           return string;
         }
         var strSymbols = stringToArray(string),
             end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
    
         return castSlice(strSymbols, 0, end).join();
       }
    
       /**
        * Removes leading whitespace or specified characters from `string`.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category String
        * @param {string} [string=] The string to trim.
        * @param {string} [chars=whitespace] The characters to trim.
        * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
        * @returns {string} Returns the trimmed string.
        * @example
        *
        * _.trimStart('  abc  ');
        * // => 'abc  '
        *
        * _.trimStart('-_-abc-_-', '_-');
        * // => 'abc-_-'
        */
       function trimStart(string, chars, guard) {
         string = toString(string);
         if (string && (guard || chars === undefined)) {
           return string.replace(reTrimStart, );
         }
         if (!string || !(chars = baseToString(chars))) {
           return string;
         }
         var strSymbols = stringToArray(string),
             start = charsStartIndex(strSymbols, stringToArray(chars));
    
         return castSlice(strSymbols, start).join();
       }
    
       /**
        * Truncates `string` if it's longer than the given maximum string length.
        * The last characters of the truncated string are replaced with the omission
        * string which defaults to "...".
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category String
        * @param {string} [string=] The string to truncate.
        * @param {Object} [options={}] The options object.
        * @param {number} [options.length=30] The maximum string length.
        * @param {string} [options.omission='...'] The string to indicate text is omitted.
        * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
        * @returns {string} Returns the truncated string.
        * @example
        *
        * _.truncate('hi-diddly-ho there, neighborino');
        * // => 'hi-diddly-ho there, neighbo...'
        *
        * _.truncate('hi-diddly-ho there, neighborino', {
        *   'length': 24,
        *   'separator': ' '
        * });
        * // => 'hi-diddly-ho there,...'
        *
        * _.truncate('hi-diddly-ho there, neighborino', {
        *   'length': 24,
        *   'separator': /,? +/
        * });
        * // => 'hi-diddly-ho there...'
        *
        * _.truncate('hi-diddly-ho there, neighborino', {
        *   'omission': ' [...]'
        * });
        * // => 'hi-diddly-ho there, neig [...]'
        */
       function truncate(string, options) {
         var length = DEFAULT_TRUNC_LENGTH,
             omission = DEFAULT_TRUNC_OMISSION;
    
         if (isObject(options)) {
           var separator = 'separator' in options ? options.separator : separator;
           length = 'length' in options ? toInteger(options.length) : length;
           omission = 'omission' in options ? baseToString(options.omission) : omission;
         }
         string = toString(string);
    
         var strLength = string.length;
         if (hasUnicode(string)) {
           var strSymbols = stringToArray(string);
           strLength = strSymbols.length;
         }
         if (length >= strLength) {
           return string;
         }
         var end = length - stringSize(omission);
         if (end < 1) {
           return omission;
         }
         var result = strSymbols
           ? castSlice(strSymbols, 0, end).join()
           : string.slice(0, end);
    
         if (separator === undefined) {
           return result + omission;
         }
         if (strSymbols) {
           end += (result.length - end);
         }
         if (isRegExp(separator)) {
           if (string.slice(end).search(separator)) {
             var match,
                 substring = result;
    
             if (!separator.global) {
               separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
             }
             separator.lastIndex = 0;
             while ((match = separator.exec(substring))) {
               var newEnd = match.index;
             }
             result = result.slice(0, newEnd === undefined ? end : newEnd);
           }
         } else if (string.indexOf(baseToString(separator), end) != end) {
           var index = result.lastIndexOf(separator);
           if (index > -1) {
             result = result.slice(0, index);
           }
         }
         return result + omission;
       }
    
       /**
        * The inverse of `_.escape`; this method converts the HTML entities
        * `&`, `<`, `>`, `"`, and `'` in `string` to
        * their corresponding characters.
        *
        * **Note:** No other HTML entities are unescaped. To unescape additional
        * HTML entities use a third-party library like [_he_](https://mths.be/he).
        *
        * @static
        * @memberOf _
        * @since 0.6.0
        * @category String
        * @param {string} [string=] The string to unescape.
        * @returns {string} Returns the unescaped string.
        * @example
        *
        * _.unescape('fred, barney, & pebbles');
        * // => 'fred, barney, & pebbles'
        */
       function unescape(string) {
         string = toString(string);
         return (string && reHasEscapedHtml.test(string))
           ? string.replace(reEscapedHtml, unescapeHtmlChar)
           : string;
       }
    
       /**
        * Converts `string`, as space separated words, to upper case.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category String
        * @param {string} [string=] The string to convert.
        * @returns {string} Returns the upper cased string.
        * @example
        *
        * _.upperCase('--foo-bar');
        * // => 'FOO BAR'
        *
        * _.upperCase('fooBar');
        * // => 'FOO BAR'
        *
        * _.upperCase('__foo_bar__');
        * // => 'FOO BAR'
        */
       var upperCase = createCompounder(function(result, word, index) {
         return result + (index ? ' ' : ) + word.toUpperCase();
       });
    
       /**
        * Converts the first character of `string` to upper case.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category String
        * @param {string} [string=] The string to convert.
        * @returns {string} Returns the converted string.
        * @example
        *
        * _.upperFirst('fred');
        * // => 'Fred'
        *
        * _.upperFirst('FRED');
        * // => 'FRED'
        */
       var upperFirst = createCaseFirst('toUpperCase');
    
       /**
        * Splits `string` into an array of its words.
        *
        * @static
        * @memberOf _
        * @since 3.0.0
        * @category String
        * @param {string} [string=] The string to inspect.
        * @param {RegExp|string} [pattern] The pattern to match words.
        * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
        * @returns {Array} Returns the words of `string`.
        * @example
        *
        * _.words('fred, barney, & pebbles');
        * // => ['fred', 'barney', 'pebbles']
        *
        * _.words('fred, barney, & pebbles', /[^, ]+/g);
        * // => ['fred', 'barney', '&', 'pebbles']
        */
       function words(string, pattern, guard) {
         string = toString(string);
         pattern = guard ? undefined : pattern;
    
         if (pattern === undefined) {
           return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
         }
         return string.match(pattern) || [];
       }
    
       /*------------------------------------------------------------------------*/
    
       /**
        * Attempts to invoke `func`, returning either the result or the caught error
        * object. Any additional arguments are provided to `func` when it's invoked.
        *
        * @static
        * @memberOf _
        * @since 3.0.0
        * @category Util
        * @param {Function} func The function to attempt.
        * @param {...*} [args] The arguments to invoke `func` with.
        * @returns {*} Returns the `func` result or error object.
        * @example
        *
        * // Avoid throwing errors for invalid selectors.
        * var elements = _.attempt(function(selector) {
        *   return document.querySelectorAll(selector);
        * }, '>_>');
        *
        * if (_.isError(elements)) {
        *   elements = [];
        * }
        */
       var attempt = baseRest(function(func, args) {
         try {
           return apply(func, undefined, args);
         } catch (e) {
           return isError(e) ? e : new Error(e);
         }
       });
    
       /**
        * Binds methods of an object to the object itself, overwriting the existing
        * method.
        *
        * **Note:** This method doesn't set the "length" property of bound functions.
        *
        * @static
        * @since 0.1.0
        * @memberOf _
        * @category Util
        * @param {Object} object The object to bind and assign the bound methods to.
        * @param {...(string|string[])} methodNames The object method names to bind.
        * @returns {Object} Returns `object`.
        * @example
        *
        * var view = {
        *   'label': 'docs',
        *   'click': function() {
        *     console.log('clicked ' + this.label);
        *   }
        * };
        *
        * _.bindAll(view, ['click']);
        * jQuery(element).on('click', view.click);
        * // => Logs 'clicked docs' when clicked.
        */
       var bindAll = flatRest(function(object, methodNames) {
         arrayEach(methodNames, function(key) {
           key = toKey(key);
           baseAssignValue(object, key, bind(object[key], object));
         });
         return object;
       });
    
       /**
        * Creates a function that iterates over `pairs` and invokes the corresponding
        * function of the first predicate to return truthy. The predicate-function
        * pairs are invoked with the `this` binding and arguments of the created
        * function.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Util
        * @param {Array} pairs The predicate-function pairs.
        * @returns {Function} Returns the new composite function.
        * @example
        *
        * var func = _.cond([
        *   [_.matches({ 'a': 1 }),           _.constant('matches A')],
        *   [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
        *   [_.stubTrue,                      _.constant('no match')]
        * ]);
        *
        * func({ 'a': 1, 'b': 2 });
        * // => 'matches A'
        *
        * func({ 'a': 0, 'b': 1 });
        * // => 'matches B'
        *
        * func({ 'a': '1', 'b': '2' });
        * // => 'no match'
        */
       function cond(pairs) {
         var length = pairs == null ? 0 : pairs.length,
             toIteratee = getIteratee();
    
         pairs = !length ? [] : arrayMap(pairs, function(pair) {
           if (typeof pair[1] != 'function') {
             throw new TypeError(FUNC_ERROR_TEXT);
           }
           return [toIteratee(pair[0]), pair[1]];
         });
    
         return baseRest(function(args) {
           var index = -1;
           while (++index < length) {
             var pair = pairs[index];
             if (apply(pair[0], this, args)) {
               return apply(pair[1], this, args);
             }
           }
         });
       }
    
       /**
        * Creates a function that invokes the predicate properties of `source` with
        * the corresponding property values of a given object, returning `true` if
        * all predicates return truthy, else `false`.
        *
        * **Note:** The created function is equivalent to `_.conformsTo` with
        * `source` partially applied.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Util
        * @param {Object} source The object of property predicates to conform to.
        * @returns {Function} Returns the new spec function.
        * @example
        *
        * var objects = [
        *   { 'a': 2, 'b': 1 },
        *   { 'a': 1, 'b': 2 }
        * ];
        *
        * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
        * // => [{ 'a': 1, 'b': 2 }]
        */
       function conforms(source) {
         return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
       }
    
       /**
        * Creates a function that returns `value`.
        *
        * @static
        * @memberOf _
        * @since 2.4.0
        * @category Util
        * @param {*} value The value to return from the new function.
        * @returns {Function} Returns the new constant function.
        * @example
        *
        * var objects = _.times(2, _.constant({ 'a': 1 }));
        *
        * console.log(objects);
        * // => [{ 'a': 1 }, { 'a': 1 }]
        *
        * console.log(objects[0] === objects[1]);
        * // => true
        */
       function constant(value) {
         return function() {
           return value;
         };
       }
    
       /**
        * Checks `value` to determine whether a default value should be returned in
        * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
        * or `undefined`.
        *
        * @static
        * @memberOf _
        * @since 4.14.0
        * @category Util
        * @param {*} value The value to check.
        * @param {*} defaultValue The default value.
        * @returns {*} Returns the resolved value.
        * @example
        *
        * _.defaultTo(1, 10);
        * // => 1
        *
        * _.defaultTo(undefined, 10);
        * // => 10
        */
       function defaultTo(value, defaultValue) {
         return (value == null || value !== value) ? defaultValue : value;
       }
    
       /**
        * Creates a function that returns the result of invoking the given functions
        * with the `this` binding of the created function, where each successive
        * invocation is supplied the return value of the previous.
        *
        * @static
        * @memberOf _
        * @since 3.0.0
        * @category Util
        * @param {...(Function|Function[])} [funcs] The functions to invoke.
        * @returns {Function} Returns the new composite function.
        * @see _.flowRight
        * @example
        *
        * function square(n) {
        *   return n * n;
        * }
        *
        * var addSquare = _.flow([_.add, square]);
        * addSquare(1, 2);
        * // => 9
        */
       var flow = createFlow();
    
       /**
        * This method is like `_.flow` except that it creates a function that
        * invokes the given functions from right to left.
        *
        * @static
        * @since 3.0.0
        * @memberOf _
        * @category Util
        * @param {...(Function|Function[])} [funcs] The functions to invoke.
        * @returns {Function} Returns the new composite function.
        * @see _.flow
        * @example
        *
        * function square(n) {
        *   return n * n;
        * }
        *
        * var addSquare = _.flowRight([square, _.add]);
        * addSquare(1, 2);
        * // => 9
        */
       var flowRight = createFlow(true);
    
       /**
        * This method returns the first argument it receives.
        *
        * @static
        * @since 0.1.0
        * @memberOf _
        * @category Util
        * @param {*} value Any value.
        * @returns {*} Returns `value`.
        * @example
        *
        * var object = { 'a': 1 };
        *
        * console.log(_.identity(object) === object);
        * // => true
        */
       function identity(value) {
         return value;
       }
    
       /**
        * Creates a function that invokes `func` with the arguments of the created
        * function. If `func` is a property name, the created function returns the
        * property value for a given element. If `func` is an array or object, the
        * created function returns `true` for elements that contain the equivalent
        * source properties, otherwise it returns `false`.
        *
        * @static
        * @since 4.0.0
        * @memberOf _
        * @category Util
        * @param {*} [func=_.identity] The value to convert to a callback.
        * @returns {Function} Returns the callback.
        * @example
        *
        * var users = [
        *   { 'user': 'barney', 'age': 36, 'active': true },
        *   { 'user': 'fred',   'age': 40, 'active': false }
        * ];
        *
        * // The `_.matches` iteratee shorthand.
        * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
        * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
        *
        * // The `_.matchesProperty` iteratee shorthand.
        * _.filter(users, _.iteratee(['user', 'fred']));
        * // => [{ 'user': 'fred', 'age': 40 }]
        *
        * // The `_.property` iteratee shorthand.
        * _.map(users, _.iteratee('user'));
        * // => ['barney', 'fred']
        *
        * // Create custom iteratee shorthands.
        * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
        *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
        *     return func.test(string);
        *   };
        * });
        *
        * _.filter(['abc', 'def'], /ef/);
        * // => ['def']
        */
       function iteratee(func) {
         return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
       }
    
       /**
        * Creates a function that performs a partial deep comparison between a given
        * object and `source`, returning `true` if the given object has equivalent
        * property values, else `false`.
        *
        * **Note:** The created function is equivalent to `_.isMatch` with `source`
        * partially applied.
        *
        * Partial comparisons will match empty array and empty object `source`
        * values against any array or object value, respectively. See `_.isEqual`
        * for a list of supported value comparisons.
        *
        * @static
        * @memberOf _
        * @since 3.0.0
        * @category Util
        * @param {Object} source The object of property values to match.
        * @returns {Function} Returns the new spec function.
        * @example
        *
        * var objects = [
        *   { 'a': 1, 'b': 2, 'c': 3 },
        *   { 'a': 4, 'b': 5, 'c': 6 }
        * ];
        *
        * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
        * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
        */
       function matches(source) {
         return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
       }
    
       /**
        * Creates a function that performs a partial deep comparison between the
        * value at `path` of a given object to `srcValue`, returning `true` if the
        * object value is equivalent, else `false`.
        *
        * **Note:** Partial comparisons will match empty array and empty object
        * `srcValue` values against any array or object value, respectively. See
        * `_.isEqual` for a list of supported value comparisons.
        *
        * @static
        * @memberOf _
        * @since 3.2.0
        * @category Util
        * @param {Array|string} path The path of the property to get.
        * @param {*} srcValue The value to match.
        * @returns {Function} Returns the new spec function.
        * @example
        *
        * var objects = [
        *   { 'a': 1, 'b': 2, 'c': 3 },
        *   { 'a': 4, 'b': 5, 'c': 6 }
        * ];
        *
        * _.find(objects, _.matchesProperty('a', 4));
        * // => { 'a': 4, 'b': 5, 'c': 6 }
        */
       function matchesProperty(path, srcValue) {
         return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
       }
    
       /**
        * Creates a function that invokes the method at `path` of a given object.
        * Any additional arguments are provided to the invoked method.
        *
        * @static
        * @memberOf _
        * @since 3.7.0
        * @category Util
        * @param {Array|string} path The path of the method to invoke.
        * @param {...*} [args] The arguments to invoke the method with.
        * @returns {Function} Returns the new invoker function.
        * @example
        *
        * var objects = [
        *   { 'a': { 'b': _.constant(2) } },
        *   { 'a': { 'b': _.constant(1) } }
        * ];
        *
        * _.map(objects, _.method('a.b'));
        * // => [2, 1]
        *
        * _.map(objects, _.method(['a', 'b']));
        * // => [2, 1]
        */
       var method = baseRest(function(path, args) {
         return function(object) {
           return baseInvoke(object, path, args);
         };
       });
    
       /**
        * The opposite of `_.method`; this method creates a function that invokes
        * the method at a given path of `object`. Any additional arguments are
        * provided to the invoked method.
        *
        * @static
        * @memberOf _
        * @since 3.7.0
        * @category Util
        * @param {Object} object The object to query.
        * @param {...*} [args] The arguments to invoke the method with.
        * @returns {Function} Returns the new invoker function.
        * @example
        *
        * var array = _.times(3, _.constant),
        *     object = { 'a': array, 'b': array, 'c': array };
        *
        * _.map(['a[2]', 'c[0]'], _.methodOf(object));
        * // => [2, 0]
        *
        * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
        * // => [2, 0]
        */
       var methodOf = baseRest(function(object, args) {
         return function(path) {
           return baseInvoke(object, path, args);
         };
       });
    
       /**
        * Adds all own enumerable string keyed function properties of a source
        * object to the destination object. If `object` is a function, then methods
        * are added to its prototype as well.
        *
        * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
        * avoid conflicts caused by modifying the original.
        *
        * @static
        * @since 0.1.0
        * @memberOf _
        * @category Util
        * @param {Function|Object} [object=lodash] The destination object.
        * @param {Object} source The object of functions to add.
        * @param {Object} [options={}] The options object.
        * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
        * @returns {Function|Object} Returns `object`.
        * @example
        *
        * function vowels(string) {
        *   return _.filter(string, function(v) {
        *     return /[aeiou]/i.test(v);
        *   });
        * }
        *
        * _.mixin({ 'vowels': vowels });
        * _.vowels('fred');
        * // => ['e']
        *
        * _('fred').vowels().value();
        * // => ['e']
        *
        * _.mixin({ 'vowels': vowels }, { 'chain': false });
        * _('fred').vowels();
        * // => ['e']
        */
       function mixin(object, source, options) {
         var props = keys(source),
             methodNames = baseFunctions(source, props);
    
         if (options == null &&
             !(isObject(source) && (methodNames.length || !props.length))) {
           options = source;
           source = object;
           object = this;
           methodNames = baseFunctions(source, keys(source));
         }
         var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
             isFunc = isFunction(object);
    
         arrayEach(methodNames, function(methodName) {
           var func = source[methodName];
           object[methodName] = func;
           if (isFunc) {
             object.prototype[methodName] = function() {
               var chainAll = this.__chain__;
               if (chain || chainAll) {
                 var result = object(this.__wrapped__),
                     actions = result.__actions__ = copyArray(this.__actions__);
    
                 actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
                 result.__chain__ = chainAll;
                 return result;
               }
               return func.apply(object, arrayPush([this.value()], arguments));
             };
           }
         });
    
         return object;
       }
    
       /**
        * Reverts the `_` variable to its previous value and returns a reference to
        * the `lodash` function.
        *
        * @static
        * @since 0.1.0
        * @memberOf _
        * @category Util
        * @returns {Function} Returns the `lodash` function.
        * @example
        *
        * var lodash = _.noConflict();
        */
       function noConflict() {
         if (root._ === this) {
           root._ = oldDash;
         }
         return this;
       }
    
       /**
        * This method returns `undefined`.
        *
        * @static
        * @memberOf _
        * @since 2.3.0
        * @category Util
        * @example
        *
        * _.times(2, _.noop);
        * // => [undefined, undefined]
        */
       function noop() {
         // No operation performed.
       }
    
       /**
        * Creates a function that gets the argument at index `n`. If `n` is negative,
        * the nth argument from the end is returned.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Util
        * @param {number} [n=0] The index of the argument to return.
        * @returns {Function} Returns the new pass-thru function.
        * @example
        *
        * var func = _.nthArg(1);
        * func('a', 'b', 'c', 'd');
        * // => 'b'
        *
        * var func = _.nthArg(-2);
        * func('a', 'b', 'c', 'd');
        * // => 'c'
        */
       function nthArg(n) {
         n = toInteger(n);
         return baseRest(function(args) {
           return baseNth(args, n);
         });
       }
    
       /**
        * Creates a function that invokes `iteratees` with the arguments it receives
        * and returns their results.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Util
        * @param {...(Function|Function[])} [iteratees=[_.identity]]
        *  The iteratees to invoke.
        * @returns {Function} Returns the new function.
        * @example
        *
        * var func = _.over([Math.max, Math.min]);
        *
        * func(1, 2, 3, 4);
        * // => [4, 1]
        */
       var over = createOver(arrayMap);
    
       /**
        * Creates a function that checks if **all** of the `predicates` return
        * truthy when invoked with the arguments it receives.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Util
        * @param {...(Function|Function[])} [predicates=[_.identity]]
        *  The predicates to check.
        * @returns {Function} Returns the new function.
        * @example
        *
        * var func = _.overEvery([Boolean, isFinite]);
        *
        * func('1');
        * // => true
        *
        * func(null);
        * // => false
        *
        * func(NaN);
        * // => false
        */
       var overEvery = createOver(arrayEvery);
    
       /**
        * Creates a function that checks if **any** of the `predicates` return
        * truthy when invoked with the arguments it receives.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Util
        * @param {...(Function|Function[])} [predicates=[_.identity]]
        *  The predicates to check.
        * @returns {Function} Returns the new function.
        * @example
        *
        * var func = _.overSome([Boolean, isFinite]);
        *
        * func('1');
        * // => true
        *
        * func(null);
        * // => true
        *
        * func(NaN);
        * // => false
        */
       var overSome = createOver(arraySome);
    
       /**
        * Creates a function that returns the value at `path` of a given object.
        *
        * @static
        * @memberOf _
        * @since 2.4.0
        * @category Util
        * @param {Array|string} path The path of the property to get.
        * @returns {Function} Returns the new accessor function.
        * @example
        *
        * var objects = [
        *   { 'a': { 'b': 2 } },
        *   { 'a': { 'b': 1 } }
        * ];
        *
        * _.map(objects, _.property('a.b'));
        * // => [2, 1]
        *
        * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
        * // => [1, 2]
        */
       function property(path) {
         return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
       }
    
       /**
        * The opposite of `_.property`; this method creates a function that returns
        * the value at a given path of `object`.
        *
        * @static
        * @memberOf _
        * @since 3.0.0
        * @category Util
        * @param {Object} object The object to query.
        * @returns {Function} Returns the new accessor function.
        * @example
        *
        * var array = [0, 1, 2],
        *     object = { 'a': array, 'b': array, 'c': array };
        *
        * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
        * // => [2, 0]
        *
        * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
        * // => [2, 0]
        */
       function propertyOf(object) {
         return function(path) {
           return object == null ? undefined : baseGet(object, path);
         };
       }
    
       /**
        * Creates an array of numbers (positive and/or negative) progressing from
        * `start` up to, but not including, `end`. A step of `-1` is used if a negative
        * `start` is specified without an `end` or `step`. If `end` is not specified,
        * it's set to `start` with `start` then set to `0`.
        *
        * **Note:** JavaScript follows the IEEE-754 standard for resolving
        * floating-point values which can produce unexpected results.
        *
        * @static
        * @since 0.1.0
        * @memberOf _
        * @category Util
        * @param {number} [start=0] The start of the range.
        * @param {number} end The end of the range.
        * @param {number} [step=1] The value to increment or decrement by.
        * @returns {Array} Returns the range of numbers.
        * @see _.inRange, _.rangeRight
        * @example
        *
        * _.range(4);
        * // => [0, 1, 2, 3]
        *
        * _.range(-4);
        * // => [0, -1, -2, -3]
        *
        * _.range(1, 5);
        * // => [1, 2, 3, 4]
        *
        * _.range(0, 20, 5);
        * // => [0, 5, 10, 15]
        *
        * _.range(0, -4, -1);
        * // => [0, -1, -2, -3]
        *
        * _.range(1, 4, 0);
        * // => [1, 1, 1]
        *
        * _.range(0);
        * // => []
        */
       var range = createRange();
    
       /**
        * This method is like `_.range` except that it populates values in
        * descending order.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Util
        * @param {number} [start=0] The start of the range.
        * @param {number} end The end of the range.
        * @param {number} [step=1] The value to increment or decrement by.
        * @returns {Array} Returns the range of numbers.
        * @see _.inRange, _.range
        * @example
        *
        * _.rangeRight(4);
        * // => [3, 2, 1, 0]
        *
        * _.rangeRight(-4);
        * // => [-3, -2, -1, 0]
        *
        * _.rangeRight(1, 5);
        * // => [4, 3, 2, 1]
        *
        * _.rangeRight(0, 20, 5);
        * // => [15, 10, 5, 0]
        *
        * _.rangeRight(0, -4, -1);
        * // => [-3, -2, -1, 0]
        *
        * _.rangeRight(1, 4, 0);
        * // => [1, 1, 1]
        *
        * _.rangeRight(0);
        * // => []
        */
       var rangeRight = createRange(true);
    
       /**
        * This method returns a new empty array.
        *
        * @static
        * @memberOf _
        * @since 4.13.0
        * @category Util
        * @returns {Array} Returns the new empty array.
        * @example
        *
        * var arrays = _.times(2, _.stubArray);
        *
        * console.log(arrays);
        * // => [[], []]
        *
        * console.log(arrays[0] === arrays[1]);
        * // => false
        */
       function stubArray() {
         return [];
       }
    
       /**
        * This method returns `false`.
        *
        * @static
        * @memberOf _
        * @since 4.13.0
        * @category Util
        * @returns {boolean} Returns `false`.
        * @example
        *
        * _.times(2, _.stubFalse);
        * // => [false, false]
        */
       function stubFalse() {
         return false;
       }
    
       /**
        * This method returns a new empty object.
        *
        * @static
        * @memberOf _
        * @since 4.13.0
        * @category Util
        * @returns {Object} Returns the new empty object.
        * @example
        *
        * var objects = _.times(2, _.stubObject);
        *
        * console.log(objects);
        * // => [{}, {}]
        *
        * console.log(objects[0] === objects[1]);
        * // => false
        */
       function stubObject() {
         return {};
       }
    
       /**
        * This method returns an empty string.
        *
        * @static
        * @memberOf _
        * @since 4.13.0
        * @category Util
        * @returns {string} Returns the empty string.
        * @example
        *
        * _.times(2, _.stubString);
        * // => [, ]
        */
       function stubString() {
         return ;
       }
    
       /**
        * This method returns `true`.
        *
        * @static
        * @memberOf _
        * @since 4.13.0
        * @category Util
        * @returns {boolean} Returns `true`.
        * @example
        *
        * _.times(2, _.stubTrue);
        * // => [true, true]
        */
       function stubTrue() {
         return true;
       }
    
       /**
        * Invokes the iteratee `n` times, returning an array of the results of
        * each invocation. The iteratee is invoked with one argument; (index).
        *
        * @static
        * @since 0.1.0
        * @memberOf _
        * @category Util
        * @param {number} n The number of times to invoke `iteratee`.
        * @param {Function} [iteratee=_.identity] The function invoked per iteration.
        * @returns {Array} Returns the array of results.
        * @example
        *
        * _.times(3, String);
        * // => ['0', '1', '2']
        *
        *  _.times(4, _.constant(0));
        * // => [0, 0, 0, 0]
        */
       function times(n, iteratee) {
         n = toInteger(n);
         if (n < 1 || n > MAX_SAFE_INTEGER) {
           return [];
         }
         var index = MAX_ARRAY_LENGTH,
             length = nativeMin(n, MAX_ARRAY_LENGTH);
    
         iteratee = getIteratee(iteratee);
         n -= MAX_ARRAY_LENGTH;
    
         var result = baseTimes(length, iteratee);
         while (++index < n) {
           iteratee(index);
         }
         return result;
       }
    
       /**
        * Converts `value` to a property path array.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Util
        * @param {*} value The value to convert.
        * @returns {Array} Returns the new property path array.
        * @example
        *
        * _.toPath('a.b.c');
        * // => ['a', 'b', 'c']
        *
        * _.toPath('a[0].b.c');
        * // => ['a', '0', 'b', 'c']
        */
       function toPath(value) {
         if (isArray(value)) {
           return arrayMap(value, toKey);
         }
         return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
       }
    
       /**
        * Generates a unique ID. If `prefix` is given, the ID is appended to it.
        *
        * @static
        * @since 0.1.0
        * @memberOf _
        * @category Util
        * @param {string} [prefix=] The value to prefix the ID with.
        * @returns {string} Returns the unique ID.
        * @example
        *
        * _.uniqueId('contact_');
        * // => 'contact_104'
        *
        * _.uniqueId();
        * // => '105'
        */
       function uniqueId(prefix) {
         var id = ++idCounter;
         return toString(prefix) + id;
       }
    
       /*------------------------------------------------------------------------*/
    
       /**
        * Adds two numbers.
        *
        * @static
        * @memberOf _
        * @since 3.4.0
        * @category Math
        * @param {number} augend The first number in an addition.
        * @param {number} addend The second number in an addition.
        * @returns {number} Returns the total.
        * @example
        *
        * _.add(6, 4);
        * // => 10
        */
       var add = createMathOperation(function(augend, addend) {
         return augend + addend;
       }, 0);
    
       /**
        * Computes `number` rounded up to `precision`.
        *
        * @static
        * @memberOf _
        * @since 3.10.0
        * @category Math
        * @param {number} number The number to round up.
        * @param {number} [precision=0] The precision to round up to.
        * @returns {number} Returns the rounded up number.
        * @example
        *
        * _.ceil(4.006);
        * // => 5
        *
        * _.ceil(6.004, 2);
        * // => 6.01
        *
        * _.ceil(6040, -2);
        * // => 6100
        */
       var ceil = createRound('ceil');
    
       /**
        * Divide two numbers.
        *
        * @static
        * @memberOf _
        * @since 4.7.0
        * @category Math
        * @param {number} dividend The first number in a division.
        * @param {number} divisor The second number in a division.
        * @returns {number} Returns the quotient.
        * @example
        *
        * _.divide(6, 4);
        * // => 1.5
        */
       var divide = createMathOperation(function(dividend, divisor) {
         return dividend / divisor;
       }, 1);
    
       /**
        * Computes `number` rounded down to `precision`.
        *
        * @static
        * @memberOf _
        * @since 3.10.0
        * @category Math
        * @param {number} number The number to round down.
        * @param {number} [precision=0] The precision to round down to.
        * @returns {number} Returns the rounded down number.
        * @example
        *
        * _.floor(4.006);
        * // => 4
        *
        * _.floor(0.046, 2);
        * // => 0.04
        *
        * _.floor(4060, -2);
        * // => 4000
        */
       var floor = createRound('floor');
    
       /**
        * Computes the maximum value of `array`. If `array` is empty or falsey,
        * `undefined` is returned.
        *
        * @static
        * @since 0.1.0
        * @memberOf _
        * @category Math
        * @param {Array} array The array to iterate over.
        * @returns {*} Returns the maximum value.
        * @example
        *
        * _.max([4, 2, 8, 6]);
        * // => 8
        *
        * _.max([]);
        * // => undefined
        */
       function max(array) {
         return (array && array.length)
           ? baseExtremum(array, identity, baseGt)
           : undefined;
       }
    
       /**
        * This method is like `_.max` except that it accepts `iteratee` which is
        * invoked for each element in `array` to generate the criterion by which
        * the value is ranked. The iteratee is invoked with one argument: (value).
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Math
        * @param {Array} array The array to iterate over.
        * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
        * @returns {*} Returns the maximum value.
        * @example
        *
        * var objects = [{ 'n': 1 }, { 'n': 2 }];
        *
        * _.maxBy(objects, function(o) { return o.n; });
        * // => { 'n': 2 }
        *
        * // The `_.property` iteratee shorthand.
        * _.maxBy(objects, 'n');
        * // => { 'n': 2 }
        */
       function maxBy(array, iteratee) {
         return (array && array.length)
           ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
           : undefined;
       }
    
       /**
        * Computes the mean of the values in `array`.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Math
        * @param {Array} array The array to iterate over.
        * @returns {number} Returns the mean.
        * @example
        *
        * _.mean([4, 2, 8, 6]);
        * // => 5
        */
       function mean(array) {
         return baseMean(array, identity);
       }
    
       /**
        * This method is like `_.mean` except that it accepts `iteratee` which is
        * invoked for each element in `array` to generate the value to be averaged.
        * The iteratee is invoked with one argument: (value).
        *
        * @static
        * @memberOf _
        * @since 4.7.0
        * @category Math
        * @param {Array} array The array to iterate over.
        * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
        * @returns {number} Returns the mean.
        * @example
        *
        * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
        *
        * _.meanBy(objects, function(o) { return o.n; });
        * // => 5
        *
        * // The `_.property` iteratee shorthand.
        * _.meanBy(objects, 'n');
        * // => 5
        */
       function meanBy(array, iteratee) {
         return baseMean(array, getIteratee(iteratee, 2));
       }
    
       /**
        * Computes the minimum value of `array`. If `array` is empty or falsey,
        * `undefined` is returned.
        *
        * @static
        * @since 0.1.0
        * @memberOf _
        * @category Math
        * @param {Array} array The array to iterate over.
        * @returns {*} Returns the minimum value.
        * @example
        *
        * _.min([4, 2, 8, 6]);
        * // => 2
        *
        * _.min([]);
        * // => undefined
        */
       function min(array) {
         return (array && array.length)
           ? baseExtremum(array, identity, baseLt)
           : undefined;
       }
    
       /**
        * This method is like `_.min` except that it accepts `iteratee` which is
        * invoked for each element in `array` to generate the criterion by which
        * the value is ranked. The iteratee is invoked with one argument: (value).
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Math
        * @param {Array} array The array to iterate over.
        * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
        * @returns {*} Returns the minimum value.
        * @example
        *
        * var objects = [{ 'n': 1 }, { 'n': 2 }];
        *
        * _.minBy(objects, function(o) { return o.n; });
        * // => { 'n': 1 }
        *
        * // The `_.property` iteratee shorthand.
        * _.minBy(objects, 'n');
        * // => { 'n': 1 }
        */
       function minBy(array, iteratee) {
         return (array && array.length)
           ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
           : undefined;
       }
    
       /**
        * Multiply two numbers.
        *
        * @static
        * @memberOf _
        * @since 4.7.0
        * @category Math
        * @param {number} multiplier The first number in a multiplication.
        * @param {number} multiplicand The second number in a multiplication.
        * @returns {number} Returns the product.
        * @example
        *
        * _.multiply(6, 4);
        * // => 24
        */
       var multiply = createMathOperation(function(multiplier, multiplicand) {
         return multiplier * multiplicand;
       }, 1);
    
       /**
        * Computes `number` rounded to `precision`.
        *
        * @static
        * @memberOf _
        * @since 3.10.0
        * @category Math
        * @param {number} number The number to round.
        * @param {number} [precision=0] The precision to round to.
        * @returns {number} Returns the rounded number.
        * @example
        *
        * _.round(4.006);
        * // => 4
        *
        * _.round(4.006, 2);
        * // => 4.01
        *
        * _.round(4060, -2);
        * // => 4100
        */
       var round = createRound('round');
    
       /**
        * Subtract two numbers.
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Math
        * @param {number} minuend The first number in a subtraction.
        * @param {number} subtrahend The second number in a subtraction.
        * @returns {number} Returns the difference.
        * @example
        *
        * _.subtract(6, 4);
        * // => 2
        */
       var subtract = createMathOperation(function(minuend, subtrahend) {
         return minuend - subtrahend;
       }, 0);
    
       /**
        * Computes the sum of the values in `array`.
        *
        * @static
        * @memberOf _
        * @since 3.4.0
        * @category Math
        * @param {Array} array The array to iterate over.
        * @returns {number} Returns the sum.
        * @example
        *
        * _.sum([4, 2, 8, 6]);
        * // => 20
        */
       function sum(array) {
         return (array && array.length)
           ? baseSum(array, identity)
           : 0;
       }
    
       /**
        * This method is like `_.sum` except that it accepts `iteratee` which is
        * invoked for each element in `array` to generate the value to be summed.
        * The iteratee is invoked with one argument: (value).
        *
        * @static
        * @memberOf _
        * @since 4.0.0
        * @category Math
        * @param {Array} array The array to iterate over.
        * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
        * @returns {number} Returns the sum.
        * @example
        *
        * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
        *
        * _.sumBy(objects, function(o) { return o.n; });
        * // => 20
        *
        * // The `_.property` iteratee shorthand.
        * _.sumBy(objects, 'n');
        * // => 20
        */
       function sumBy(array, iteratee) {
         return (array && array.length)
           ? baseSum(array, getIteratee(iteratee, 2))
           : 0;
       }
    
       /*------------------------------------------------------------------------*/
    
       // Add methods that return wrapped values in chain sequences.
       lodash.after = after;
       lodash.ary = ary;
       lodash.assign = assign;
       lodash.assignIn = assignIn;
       lodash.assignInWith = assignInWith;
       lodash.assignWith = assignWith;
       lodash.at = at;
       lodash.before = before;
       lodash.bind = bind;
       lodash.bindAll = bindAll;
       lodash.bindKey = bindKey;
       lodash.castArray = castArray;
       lodash.chain = chain;
       lodash.chunk = chunk;
       lodash.compact = compact;
       lodash.concat = concat;
       lodash.cond = cond;
       lodash.conforms = conforms;
       lodash.constant = constant;
       lodash.countBy = countBy;
       lodash.create = create;
       lodash.curry = curry;
       lodash.curryRight = curryRight;
       lodash.debounce = debounce;
       lodash.defaults = defaults;
       lodash.defaultsDeep = defaultsDeep;
       lodash.defer = defer;
       lodash.delay = delay;
       lodash.difference = difference;
       lodash.differenceBy = differenceBy;
       lodash.differenceWith = differenceWith;
       lodash.drop = drop;
       lodash.dropRight = dropRight;
       lodash.dropRightWhile = dropRightWhile;
       lodash.dropWhile = dropWhile;
       lodash.fill = fill;
       lodash.filter = filter;
       lodash.flatMap = flatMap;
       lodash.flatMapDeep = flatMapDeep;
       lodash.flatMapDepth = flatMapDepth;
       lodash.flatten = flatten;
       lodash.flattenDeep = flattenDeep;
       lodash.flattenDepth = flattenDepth;
       lodash.flip = flip;
       lodash.flow = flow;
       lodash.flowRight = flowRight;
       lodash.fromPairs = fromPairs;
       lodash.functions = functions;
       lodash.functionsIn = functionsIn;
       lodash.groupBy = groupBy;
       lodash.initial = initial;
       lodash.intersection = intersection;
       lodash.intersectionBy = intersectionBy;
       lodash.intersectionWith = intersectionWith;
       lodash.invert = invert;
       lodash.invertBy = invertBy;
       lodash.invokeMap = invokeMap;
       lodash.iteratee = iteratee;
       lodash.keyBy = keyBy;
       lodash.keys = keys;
       lodash.keysIn = keysIn;
       lodash.map = map;
       lodash.mapKeys = mapKeys;
       lodash.mapValues = mapValues;
       lodash.matches = matches;
       lodash.matchesProperty = matchesProperty;
       lodash.memoize = memoize;
       lodash.merge = merge;
       lodash.mergeWith = mergeWith;
       lodash.method = method;
       lodash.methodOf = methodOf;
       lodash.mixin = mixin;
       lodash.negate = negate;
       lodash.nthArg = nthArg;
       lodash.omit = omit;
       lodash.omitBy = omitBy;
       lodash.once = once;
       lodash.orderBy = orderBy;
       lodash.over = over;
       lodash.overArgs = overArgs;
       lodash.overEvery = overEvery;
       lodash.overSome = overSome;
       lodash.partial = partial;
       lodash.partialRight = partialRight;
       lodash.partition = partition;
       lodash.pick = pick;
       lodash.pickBy = pickBy;
       lodash.property = property;
       lodash.propertyOf = propertyOf;
       lodash.pull = pull;
       lodash.pullAll = pullAll;
       lodash.pullAllBy = pullAllBy;
       lodash.pullAllWith = pullAllWith;
       lodash.pullAt = pullAt;
       lodash.range = range;
       lodash.rangeRight = rangeRight;
       lodash.rearg = rearg;
       lodash.reject = reject;
       lodash.remove = remove;
       lodash.rest = rest;
       lodash.reverse = reverse;
       lodash.sampleSize = sampleSize;
       lodash.set = set;
       lodash.setWith = setWith;
       lodash.shuffle = shuffle;
       lodash.slice = slice;
       lodash.sortBy = sortBy;
       lodash.sortedUniq = sortedUniq;
       lodash.sortedUniqBy = sortedUniqBy;
       lodash.split = split;
       lodash.spread = spread;
       lodash.tail = tail;
       lodash.take = take;
       lodash.takeRight = takeRight;
       lodash.takeRightWhile = takeRightWhile;
       lodash.takeWhile = takeWhile;
       lodash.tap = tap;
       lodash.throttle = throttle;
       lodash.thru = thru;
       lodash.toArray = toArray;
       lodash.toPairs = toPairs;
       lodash.toPairsIn = toPairsIn;
       lodash.toPath = toPath;
       lodash.toPlainObject = toPlainObject;
       lodash.transform = transform;
       lodash.unary = unary;
       lodash.union = union;
       lodash.unionBy = unionBy;
       lodash.unionWith = unionWith;
       lodash.uniq = uniq;
       lodash.uniqBy = uniqBy;
       lodash.uniqWith = uniqWith;
       lodash.unset = unset;
       lodash.unzip = unzip;
       lodash.unzipWith = unzipWith;
       lodash.update = update;
       lodash.updateWith = updateWith;
       lodash.values = values;
       lodash.valuesIn = valuesIn;
       lodash.without = without;
       lodash.words = words;
       lodash.wrap = wrap;
       lodash.xor = xor;
       lodash.xorBy = xorBy;
       lodash.xorWith = xorWith;
       lodash.zip = zip;
       lodash.zipObject = zipObject;
       lodash.zipObjectDeep = zipObjectDeep;
       lodash.zipWith = zipWith;
    
       // Add aliases.
       lodash.entries = toPairs;
       lodash.entriesIn = toPairsIn;
       lodash.extend = assignIn;
       lodash.extendWith = assignInWith;
    
       // Add methods to `lodash.prototype`.
       mixin(lodash, lodash);
    
       /*------------------------------------------------------------------------*/
    
       // Add methods that return unwrapped values in chain sequences.
       lodash.add = add;
       lodash.attempt = attempt;
       lodash.camelCase = camelCase;
       lodash.capitalize = capitalize;
       lodash.ceil = ceil;
       lodash.clamp = clamp;
       lodash.clone = clone;
       lodash.cloneDeep = cloneDeep;
       lodash.cloneDeepWith = cloneDeepWith;
       lodash.cloneWith = cloneWith;
       lodash.conformsTo = conformsTo;
       lodash.deburr = deburr;
       lodash.defaultTo = defaultTo;
       lodash.divide = divide;
       lodash.endsWith = endsWith;
       lodash.eq = eq;
       lodash.escape = escape;
       lodash.escapeRegExp = escapeRegExp;
       lodash.every = every;
       lodash.find = find;
       lodash.findIndex = findIndex;
       lodash.findKey = findKey;
       lodash.findLast = findLast;
       lodash.findLastIndex = findLastIndex;
       lodash.findLastKey = findLastKey;
       lodash.floor = floor;
       lodash.forEach = forEach;
       lodash.forEachRight = forEachRight;
       lodash.forIn = forIn;
       lodash.forInRight = forInRight;
       lodash.forOwn = forOwn;
       lodash.forOwnRight = forOwnRight;
       lodash.get = get;
       lodash.gt = gt;
       lodash.gte = gte;
       lodash.has = has;
       lodash.hasIn = hasIn;
       lodash.head = head;
       lodash.identity = identity;
       lodash.includes = includes;
       lodash.indexOf = indexOf;
       lodash.inRange = inRange;
       lodash.invoke = invoke;
       lodash.isArguments = isArguments;
       lodash.isArray = isArray;
       lodash.isArrayBuffer = isArrayBuffer;
       lodash.isArrayLike = isArrayLike;
       lodash.isArrayLikeObject = isArrayLikeObject;
       lodash.isBoolean = isBoolean;
       lodash.isBuffer = isBuffer;
       lodash.isDate = isDate;
       lodash.isElement = isElement;
       lodash.isEmpty = isEmpty;
       lodash.isEqual = isEqual;
       lodash.isEqualWith = isEqualWith;
       lodash.isError = isError;
       lodash.isFinite = isFinite;
       lodash.isFunction = isFunction;
       lodash.isInteger = isInteger;
       lodash.isLength = isLength;
       lodash.isMap = isMap;
       lodash.isMatch = isMatch;
       lodash.isMatchWith = isMatchWith;
       lodash.isNaN = isNaN;
       lodash.isNative = isNative;
       lodash.isNil = isNil;
       lodash.isNull = isNull;
       lodash.isNumber = isNumber;
       lodash.isObject = isObject;
       lodash.isObjectLike = isObjectLike;
       lodash.isPlainObject = isPlainObject;
       lodash.isRegExp = isRegExp;
       lodash.isSafeInteger = isSafeInteger;
       lodash.isSet = isSet;
       lodash.isString = isString;
       lodash.isSymbol = isSymbol;
       lodash.isTypedArray = isTypedArray;
       lodash.isUndefined = isUndefined;
       lodash.isWeakMap = isWeakMap;
       lodash.isWeakSet = isWeakSet;
       lodash.join = join;
       lodash.kebabCase = kebabCase;
       lodash.last = last;
       lodash.lastIndexOf = lastIndexOf;
       lodash.lowerCase = lowerCase;
       lodash.lowerFirst = lowerFirst;
       lodash.lt = lt;
       lodash.lte = lte;
       lodash.max = max;
       lodash.maxBy = maxBy;
       lodash.mean = mean;
       lodash.meanBy = meanBy;
       lodash.min = min;
       lodash.minBy = minBy;
       lodash.stubArray = stubArray;
       lodash.stubFalse = stubFalse;
       lodash.stubObject = stubObject;
       lodash.stubString = stubString;
       lodash.stubTrue = stubTrue;
       lodash.multiply = multiply;
       lodash.nth = nth;
       lodash.noConflict = noConflict;
       lodash.noop = noop;
       lodash.now = now;
       lodash.pad = pad;
       lodash.padEnd = padEnd;
       lodash.padStart = padStart;
       lodash.parseInt = parseInt;
       lodash.random = random;
       lodash.reduce = reduce;
       lodash.reduceRight = reduceRight;
       lodash.repeat = repeat;
       lodash.replace = replace;
       lodash.result = result;
       lodash.round = round;
       lodash.runInContext = runInContext;
       lodash.sample = sample;
       lodash.size = size;
       lodash.snakeCase = snakeCase;
       lodash.some = some;
       lodash.sortedIndex = sortedIndex;
       lodash.sortedIndexBy = sortedIndexBy;
       lodash.sortedIndexOf = sortedIndexOf;
       lodash.sortedLastIndex = sortedLastIndex;
       lodash.sortedLastIndexBy = sortedLastIndexBy;
       lodash.sortedLastIndexOf = sortedLastIndexOf;
       lodash.startCase = startCase;
       lodash.startsWith = startsWith;
       lodash.subtract = subtract;
       lodash.sum = sum;
       lodash.sumBy = sumBy;
       lodash.template = template;
       lodash.times = times;
       lodash.toFinite = toFinite;
       lodash.toInteger = toInteger;
       lodash.toLength = toLength;
       lodash.toLower = toLower;
       lodash.toNumber = toNumber;
       lodash.toSafeInteger = toSafeInteger;
       lodash.toString = toString;
       lodash.toUpper = toUpper;
       lodash.trim = trim;
       lodash.trimEnd = trimEnd;
       lodash.trimStart = trimStart;
       lodash.truncate = truncate;
       lodash.unescape = unescape;
       lodash.uniqueId = uniqueId;
       lodash.upperCase = upperCase;
       lodash.upperFirst = upperFirst;
    
       // Add aliases.
       lodash.each = forEach;
       lodash.eachRight = forEachRight;
       lodash.first = head;
    
       mixin(lodash, (function() {
         var source = {};
         baseForOwn(lodash, function(func, methodName) {
           if (!hasOwnProperty.call(lodash.prototype, methodName)) {
             source[methodName] = func;
           }
         });
         return source;
       }()), { 'chain': false });
    
       /*------------------------------------------------------------------------*/
    
       /**
        * The semantic version number.
        *
        * @static
        * @memberOf _
        * @type {string}
        */
       lodash.VERSION = VERSION;
    
       // Assign default placeholders.
       arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
         lodash[methodName].placeholder = lodash;
       });
    
       // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
       arrayEach(['drop', 'take'], function(methodName, index) {
         LazyWrapper.prototype[methodName] = function(n) {
           n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
    
           var result = (this.__filtered__ && !index)
             ? new LazyWrapper(this)
             : this.clone();
    
           if (result.__filtered__) {
             result.__takeCount__ = nativeMin(n, result.__takeCount__);
           } else {
             result.__views__.push({
               'size': nativeMin(n, MAX_ARRAY_LENGTH),
               'type': methodName + (result.__dir__ < 0 ? 'Right' : )
             });
           }
           return result;
         };
    
         LazyWrapper.prototype[methodName + 'Right'] = function(n) {
           return this.reverse()[methodName](n).reverse();
         };
       });
    
       // Add `LazyWrapper` methods that accept an `iteratee` value.
       arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
         var type = index + 1,
             isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
    
         LazyWrapper.prototype[methodName] = function(iteratee) {
           var result = this.clone();
           result.__iteratees__.push({
             'iteratee': getIteratee(iteratee, 3),
             'type': type
           });
           result.__filtered__ = result.__filtered__ || isFilter;
           return result;
         };
       });
    
       // Add `LazyWrapper` methods for `_.head` and `_.last`.
       arrayEach(['head', 'last'], function(methodName, index) {
         var takeName = 'take' + (index ? 'Right' : );
    
         LazyWrapper.prototype[methodName] = function() {
           return this[takeName](1).value()[0];
         };
       });
    
       // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
       arrayEach(['initial', 'tail'], function(methodName, index) {
         var dropName = 'drop' + (index ?  : 'Right');
    
         LazyWrapper.prototype[methodName] = function() {
           return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
         };
       });
    
       LazyWrapper.prototype.compact = function() {
         return this.filter(identity);
       };
    
       LazyWrapper.prototype.find = function(predicate) {
         return this.filter(predicate).head();
       };
    
       LazyWrapper.prototype.findLast = function(predicate) {
         return this.reverse().find(predicate);
       };
    
       LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
         if (typeof path == 'function') {
           return new LazyWrapper(this);
         }
         return this.map(function(value) {
           return baseInvoke(value, path, args);
         });
       });
    
       LazyWrapper.prototype.reject = function(predicate) {
         return this.filter(negate(getIteratee(predicate)));
       };
    
       LazyWrapper.prototype.slice = function(start, end) {
         start = toInteger(start);
    
         var result = this;
         if (result.__filtered__ && (start > 0 || end < 0)) {
           return new LazyWrapper(result);
         }
         if (start < 0) {
           result = result.takeRight(-start);
         } else if (start) {
           result = result.drop(start);
         }
         if (end !== undefined) {
           end = toInteger(end);
           result = end < 0 ? result.dropRight(-end) : result.take(end - start);
         }
         return result;
       };
    
       LazyWrapper.prototype.takeRightWhile = function(predicate) {
         return this.reverse().takeWhile(predicate).reverse();
       };
    
       LazyWrapper.prototype.toArray = function() {
         return this.take(MAX_ARRAY_LENGTH);
       };
    
       // Add `LazyWrapper` methods to `lodash.prototype`.
       baseForOwn(LazyWrapper.prototype, function(func, methodName) {
         var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
             isTaker = /^(?:head|last)$/.test(methodName),
             lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : )) : methodName],
             retUnwrapped = isTaker || /^find/.test(methodName);
    
         if (!lodashFunc) {
           return;
         }
         lodash.prototype[methodName] = function() {
           var value = this.__wrapped__,
               args = isTaker ? [1] : arguments,
               isLazy = value instanceof LazyWrapper,
               iteratee = args[0],
               useLazy = isLazy || isArray(value);
    
           var interceptor = function(value) {
             var result = lodashFunc.apply(lodash, arrayPush([value], args));
             return (isTaker && chainAll) ? result[0] : result;
           };
    
           if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
             // Avoid lazy use if the iteratee has a "length" value other than `1`.
             isLazy = useLazy = false;
           }
           var chainAll = this.__chain__,
               isHybrid = !!this.__actions__.length,
               isUnwrapped = retUnwrapped && !chainAll,
               onlyLazy = isLazy && !isHybrid;
    
           if (!retUnwrapped && useLazy) {
             value = onlyLazy ? value : new LazyWrapper(this);
             var result = func.apply(value, args);
             result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
             return new LodashWrapper(result, chainAll);
           }
           if (isUnwrapped && onlyLazy) {
             return func.apply(this, args);
           }
           result = this.thru(interceptor);
           return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
         };
       });
    
       // Add `Array` methods to `lodash.prototype`.
       arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
         var func = arrayProto[methodName],
             chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
             retUnwrapped = /^(?:pop|shift)$/.test(methodName);
    
         lodash.prototype[methodName] = function() {
           var args = arguments;
           if (retUnwrapped && !this.__chain__) {
             var value = this.value();
             return func.apply(isArray(value) ? value : [], args);
           }
           return this[chainName](function(value) {
             return func.apply(isArray(value) ? value : [], args);
           });
         };
       });
    
       // Map minified method names to their real names.
       baseForOwn(LazyWrapper.prototype, function(func, methodName) {
         var lodashFunc = lodash[methodName];
         if (lodashFunc) {
           var key = lodashFunc.name + ;
           if (!hasOwnProperty.call(realNames, key)) {
             realNames[key] = [];
           }
           realNames[key].push({ 'name': methodName, 'func': lodashFunc });
         }
       });
    
       realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
         'name': 'wrapper',
         'func': undefined
       }];
    
       // Add methods to `LazyWrapper`.
       LazyWrapper.prototype.clone = lazyClone;
       LazyWrapper.prototype.reverse = lazyReverse;
       LazyWrapper.prototype.value = lazyValue;
    
       // Add chain sequence methods to the `lodash` wrapper.
       lodash.prototype.at = wrapperAt;
       lodash.prototype.chain = wrapperChain;
       lodash.prototype.commit = wrapperCommit;
       lodash.prototype.next = wrapperNext;
       lodash.prototype.plant = wrapperPlant;
       lodash.prototype.reverse = wrapperReverse;
       lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
    
       // Add lazy aliases.
       lodash.prototype.first = lodash.prototype.head;
    
       if (symIterator) {
         lodash.prototype[symIterator] = wrapperToIterator;
       }
       return lodash;
     });
    
     /*--------------------------------------------------------------------------*/
    
     // Export lodash.
     var _ = runInContext();
    
     // Some AMD build optimizers, like r.js, check for condition patterns like:
     if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
       // Expose Lodash on the global object to prevent errors when Lodash is
       // loaded by a script tag in the presence of an AMD loader.
       // See http://requirejs.org/docs/errors.html#mismatch for more details.
       // Use `_.noConflict` to remove Lodash from the global object.
       root._ = _;
    
       // Define as an anonymous module so, through path mapping, it can be
       // referenced as the "underscore" module.
       define(function() {
         return _;
       });
     }
     // Check for `exports` after `define` in case a build optimizer adds it.
     else if (freeModule) {
       // Export for Node.js.
       (freeModule.exports = _)._ = _;
       // Export for CommonJS support.
       freeExports._ = _;
     }
     else {
       // Export to the global object.
       root._ = _;
     }
    

    }.call(this));

    }); return ___scope___.entry = "lodash.js"; }); FuseBox.pkg("mithril", {}, function(___scope___){ ___scope___.file("mithril.js", function(exports, require, module, __filename, __dirname){

    (function() {

    "use strict" function Vnode(tag, key, attrs0, children, text, dom) { return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: undefined, _state: undefined, events: undefined, instance: undefined, skip: false} } Vnode.normalize = function(node) { if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined) if (node != null && typeof node !== "object") return Vnode("#", undefined, undefined, node === false ? "" : node, undefined, undefined) return node } Vnode.normalizeChildren = function normalizeChildren(children) { for (var i = 0; i < children.length; i++) { children[i] = Vnode.normalize(children[i]) } return children } var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g var selectorCache = {} var hasOwn = {}.hasOwnProperty function isEmpty(object) { for (var key in object) if (hasOwn.call(object, key)) return false return true } function compileSelector(selector) { var match, tag = "div", classes = [], attrs = {} while (match = selectorParser.exec(selector)) { var type = match[1], value = match[2] if (type === "" && value !== "") tag = value else if (type === "#") attrs.id = value else if (type === ".") classes.push(value) else if (match[3][0] === "[") { var attrValue = match[6] if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\") if (match[4] === "class") classes.push(attrValue) else attrs[match[4]] = attrValue === "" ? attrValue : attrValue || true } } if (classes.length > 0) attrs.className = classes.join(" ") return selectorCache[selector] = {tag: tag, attrs: attrs} } function execSelector(state, attrs, children) { var hasAttrs = false, childList, text var className = attrs.className || attrs.class if (!isEmpty(state.attrs) && !isEmpty(attrs)) { var newAttrs = {} for(var key in attrs) { if (hasOwn.call(attrs, key)) { newAttrs[key] = attrs[key] } } attrs = newAttrs } for (var key in state.attrs) { if (hasOwn.call(state.attrs, key)) { attrs[key] = state.attrs[key] } } if (className !== undefined) { if (attrs.class !== undefined) { attrs.class = undefined attrs.className = className } if (state.attrs.className != null) { attrs.className = state.attrs.className + " " + className } } for (var key in attrs) { if (hasOwn.call(attrs, key) && key !== "key") { hasAttrs = true break } } if (Array.isArray(children) && children.length === 1 && children[0] != null && children[0].tag === "#") { text = children[0].children } else { childList = children } return Vnode(state.tag, attrs.key, hasAttrs ? attrs : undefined, childList, text) } function hyperscript(selector) { // Because sloppy mode sucks var attrs = arguments[1], start = 2, children if (selector == null || typeof selector !== "string" && typeof selector !== "function" && typeof selector.view !== "function") { throw Error("The selector must be either a string or a component."); } if (typeof selector === "string") { var cached = selectorCache[selector] || compileSelector(selector) } if (attrs == null) { attrs = {} } else if (typeof attrs !== "object" || attrs.tag != null || Array.isArray(attrs)) { attrs = {} start = 1 } if (arguments.length === start + 1) { children = arguments[start] if (!Array.isArray(children)) children = [children] } else { children = [] while (start < arguments.length) children.push(arguments[start++]) } var normalized = Vnode.normalizeChildren(children) if (typeof selector === "string") { return execSelector(cached, attrs, normalized) } else { return Vnode(selector, attrs.key, attrs, normalized) } } hyperscript.trust = function(html) { if (html == null) html = "" return Vnode("<", undefined, undefined, html, undefined, undefined) } hyperscript.fragment = function(attrs1, children) { return Vnode("[", attrs1.key, attrs1, Vnode.normalizeChildren(children), undefined, undefined) } var m = hyperscript /** @constructor */ var PromisePolyfill = function(executor) { if (!(this instanceof PromisePolyfill)) throw new Error("Promise must be called with `new`") if (typeof executor !== "function") throw new TypeError("executor must be a function") var self = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false) var instance = self._instance = {resolvers: resolvers, rejectors: rejectors} var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout function handler(list, shouldAbsorb) { return function execute(value) { var then try { if (shouldAbsorb && value != null && (typeof value === "object" || typeof value === "function") && typeof (then = value.then) === "function") { if (value === self) throw new TypeError("Promise can't be resolved w/ itself") executeOnce(then.bind(value)) } else { callAsync(function() { if (!shouldAbsorb && list.length === 0) console.error("Possible unhandled promise rejection:", value) for (var i = 0; i < list.length; i++) list[i](value) resolvers.length = 0, rejectors.length = 0 instance.state = shouldAbsorb instance.retry = function() {execute(value)} }) } } catch (e) { rejectCurrent(e) } } } function executeOnce(then) { var runs = 0 function run(fn) { return function(value) { if (runs++ > 0) return fn(value) } } var onerror = run(rejectCurrent) try {then(run(resolveCurrent), onerror)} catch (e) {onerror(e)} } executeOnce(executor) } PromisePolyfill.prototype.then = function(onFulfilled, onRejection) { var self = this, instance = self._instance function handle(callback, list, next, state) { list.push(function(value) { if (typeof callback !== "function") next(value) else try {resolveNext(callback(value))} catch (e) {if (rejectNext) rejectNext(e)} }) if (typeof instance.retry === "function" && state === instance.state) instance.retry() } var resolveNext, rejectNext var promise = new PromisePolyfill(function(resolve, reject) {resolveNext = resolve, rejectNext = reject}) handle(onFulfilled, instance.resolvers, resolveNext, true), handle(onRejection, instance.rejectors, rejectNext, false) return promise } PromisePolyfill.prototype.catch = function(onRejection) { return this.then(null, onRejection) } PromisePolyfill.resolve = function(value) { if (value instanceof PromisePolyfill) return value return new PromisePolyfill(function(resolve) {resolve(value)}) } PromisePolyfill.reject = function(value) { return new PromisePolyfill(function(resolve, reject) {reject(value)}) } PromisePolyfill.all = function(list) { return new PromisePolyfill(function(resolve, reject) { var total = list.length, count = 0, values = [] if (list.length === 0) resolve([]) else for (var i = 0; i < list.length; i++) { (function(i) { function consume(value) { count++ values[i] = value if (count === total) resolve(values) } if (list[i] != null && (typeof list[i] === "object" || typeof list[i] === "function") && typeof list[i].then === "function") { list[i].then(consume, reject) } else consume(list[i]) })(i) } }) } PromisePolyfill.race = function(list) { return new PromisePolyfill(function(resolve, reject) { for (var i = 0; i < list.length; i++) { list[i].then(resolve, reject) } }) } if (typeof window !== "undefined") { if (typeof window.Promise === "undefined") window.Promise = PromisePolyfill var PromisePolyfill = window.Promise } else if (typeof global !== "undefined") { if (typeof global.Promise === "undefined") global.Promise = PromisePolyfill var PromisePolyfill = global.Promise } else { } var buildQueryString = function(object) { if (Object.prototype.toString.call(object) !== "[object Object]") return "" var args = [] for (var key0 in object) { destructure(key0, object[key0]) } return args.join("&") function destructure(key0, value) { if (Array.isArray(value)) { for (var i = 0; i < value.length; i++) { destructure(key0 + "[" + i + "]", value[i]) } } else if (Object.prototype.toString.call(value) === "[object Object]") { for (var i in value) { destructure(key0 + "[" + i + "]", value[i]) } } else args.push(encodeURIComponent(key0) + (value != null && value !== "" ? "=" + encodeURIComponent(value) : "")) } } var FILE_PROTOCOL_REGEX = new RegExp("^file://", "i") var _8 = function($window, Promise) { var callbackCount = 0 var oncompletion function setCompletionCallback(callback) {oncompletion = callback} function finalizer() { var count = 0 function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()} return function finalize(promise0) { var then0 = promise0.then promise0.then = function() { count++ var next = then0.apply(promise0, arguments) next.then(complete, function(e) { complete() if (count === 0) throw e }) return finalize(next) } return promise0 } } function normalize(args, extra) { if (typeof args === "string") { var url = args args = extra || {} if (args.url == null) args.url = url } return args } function request(args, extra) { var finalize = finalizer() args = normalize(args, extra) var promise0 = new Promise(function(resolve, reject) { if (args.method == null) args.method = "GET" args.method = args.method.toUpperCase() var useBody = (args.method === "GET" || args.method === "TRACE") ? false : (typeof args.useBody === "boolean" ? args.useBody : true) if (typeof args.serialize !== "function") args.serialize = typeof FormData !== "undefined" && args.data instanceof FormData ? function(value) {return value} : JSON.stringify if (typeof args.deserialize !== "function") args.deserialize = deserialize if (typeof args.extract !== "function") args.extract = extract args.url = interpolate(args.url, args.data) if (useBody) args.data = args.serialize(args.data) else args.url = assemble(args.url, args.data) var xhr = new $window.XMLHttpRequest(), aborted = false, _abort = xhr.abort xhr.abort = function abort() { aborted = true _abort.call(xhr) } xhr.open(args.method, args.url, typeof args.async === "boolean" ? args.async : true, typeof args.user === "string" ? args.user : undefined, typeof args.password === "string" ? args.password : undefined) if (args.serialize === JSON.stringify && useBody && !(args.headers && args.headers.hasOwnProperty("Content-Type"))) { xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8") } if (args.deserialize === deserialize && !(args.headers && args.headers.hasOwnProperty("Accept"))) { xhr.setRequestHeader("Accept", "application/json, text/*") } if (args.withCredentials) xhr.withCredentials = args.withCredentials for (var key in args.headers) if ({}.hasOwnProperty.call(args.headers, key)) { xhr.setRequestHeader(key, args.headers[key]) } if (typeof args.config === "function") xhr = args.config(xhr, args) || xhr xhr.onreadystatechange = function() { // Don't throw errors on xhr.abort(). if(aborted) return if (xhr.readyState === 4) { try { var response = (args.extract !== extract) ? args.extract(xhr, args) : args.deserialize(args.extract(xhr, args)) if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || FILE_PROTOCOL_REGEX.test(args.url)) { resolve(cast(args.type, response)) } else { var error = new Error(xhr.responseText) for (var key in response) error[key] = response[key] reject(error) } } catch (e) { reject(e) } } } if (useBody && (args.data != null)) xhr.send(args.data) else xhr.send() }) return args.background === true ? promise0 : finalize(promise0) } function jsonp(args, extra) { var finalize = finalizer() args = normalize(args, extra) var promise0 = new Promise(function(resolve, reject) { var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++ var script = $window.document.createElement("script") $window[callbackName] = function(data) { script.parentNode.removeChild(script) resolve(cast(args.type, data)) delete $window[callbackName] } script.onerror = function() { script.parentNode.removeChild(script) reject(new Error("JSONP request failed")) delete $window[callbackName] } if (args.data == null) args.data = {} args.url = interpolate(args.url, args.data) args.data[args.callbackKey || "callback"] = callbackName script.src = assemble(args.url, args.data) $window.document.documentElement.appendChild(script) }) return args.background === true? promise0 : finalize(promise0) } function interpolate(url, data) { if (data == null) return url var tokens = url.match(/:[^\/]+/gi) || [] for (var i = 0; i < tokens.length; i++) { var key = tokens[i].slice(1) if (data[key] != null) { url = url.replace(tokens[i], data[key]) } } return url } function assemble(url, data) { var querystring = buildQueryString(data) if (querystring !== "") { var prefix = url.indexOf("?") < 0 ? "?" : "&" url += prefix + querystring } return url } function deserialize(data) { try {return data !== "" ? JSON.parse(data) : null} catch (e) {throw new Error(data)} } function extract(xhr) {return xhr.responseText} function cast(type0, data) { if (typeof type0 === "function") { if (Array.isArray(data)) { for (var i = 0; i < data.length; i++) { data[i] = new type0(data[i]) } } else return new type0(data) } return data } return {request: request, jsonp: jsonp, setCompletionCallback: setCompletionCallback} } var requestService = _8(window, PromisePolyfill) var coreRenderer = function($window) { var $doc = $window.document var $emptyFragment = $doc.createDocumentFragment() var nameSpace = { svg: "http://www.w3.org/2000/svg", math: "http://www.w3.org/1998/Math/MathML" } var onevent function setEventCallback(callback) {return onevent = callback} function getNameSpace(vnode) { return vnode.attrs && vnode.attrs.xmlns || nameSpace[vnode.tag] } //create function createNodes(parent, vnodes, start, end, hooks, nextSibling, ns) { for (var i = start; i < end; i++) { var vnode = vnodes[i] if (vnode != null) { createNode(parent, vnode, hooks, ns, nextSibling) } } } function createNode(parent, vnode, hooks, ns, nextSibling) { var tag = vnode.tag if (typeof tag === "string") { vnode.state = {} if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) switch (tag) { case "#": return createText(parent, vnode, nextSibling) case "<": return createHTML(parent, vnode, nextSibling) case "[": return createFragment(parent, vnode, hooks, ns, nextSibling) default: return createElement(parent, vnode, hooks, ns, nextSibling) } } else return createComponent(parent, vnode, hooks, ns, nextSibling) } function createText(parent, vnode, nextSibling) { vnode.dom = $doc.createTextNode(vnode.children) insertNode(parent, vnode.dom, nextSibling) return vnode.dom } function createHTML(parent, vnode, nextSibling) { var match1 = vnode.children.match(/^\s*?<(\w+)/im) || [] var parent1 = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"}[match1[1]] || "div" var temp = $doc.createElement(parent1) temp.innerHTML = vnode.children vnode.dom = temp.firstChild vnode.domSize = temp.childNodes.length var fragment = $doc.createDocumentFragment() var child while (child = temp.firstChild) { fragment.appendChild(child) } insertNode(parent, fragment, nextSibling) return fragment } function createFragment(parent, vnode, hooks, ns, nextSibling) { var fragment = $doc.createDocumentFragment() if (vnode.children != null) { var children = vnode.children createNodes(fragment, children, 0, children.length, hooks, null, ns) } vnode.dom = fragment.firstChild vnode.domSize = fragment.childNodes.length insertNode(parent, fragment, nextSibling) return fragment } function createElement(parent, vnode, hooks, ns, nextSibling) { var tag = vnode.tag var attrs2 = vnode.attrs var is = attrs2 && attrs2.is ns = getNameSpace(vnode) || ns var element = ns ? is ? $doc.createElementNS(ns, tag, {is: is}) : $doc.createElementNS(ns, tag) : is ? $doc.createElement(tag, {is: is}) : $doc.createElement(tag) vnode.dom = element if (attrs2 != null) { setAttrs(vnode, attrs2, ns) } insertNode(parent, element, nextSibling) if (vnode.attrs != null && vnode.attrs.contenteditable != null) { setContentEditable(vnode) } else { if (vnode.text != null) { if (vnode.text !== "") element.textContent = vnode.text else vnode.children = [Vnode("#", undefined, undefined, vnode.text, undefined, undefined)] } if (vnode.children != null) { var children = vnode.children createNodes(element, children, 0, children.length, hooks, null, ns) setLateAttrs(vnode) } } return element } function initComponent(vnode, hooks) { var sentinel if (typeof vnode.tag.view === "function") { vnode.state = Object.create(vnode.tag) sentinel = vnode.state.view if (sentinel.$$reentrantLock$$ != null) return $emptyFragment sentinel.$$reentrantLock$$ = true } else { vnode.state = void 0 sentinel = vnode.tag if (sentinel.$$reentrantLock$$ != null) return $emptyFragment sentinel.$$reentrantLock$$ = true vnode.state = (vnode.tag.prototype != null && typeof vnode.tag.prototype.view === "function") ? new vnode.tag(vnode) : vnode.tag(vnode) } vnode._state = vnode.state if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) initLifecycle(vnode._state, vnode, hooks) vnode.instance = Vnode.normalize(vnode._state.view.call(vnode.state, vnode)) if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument") sentinel.$$reentrantLock$$ = null } function createComponent(parent, vnode, hooks, ns, nextSibling) { initComponent(vnode, hooks) if (vnode.instance != null) { var element = createNode(parent, vnode.instance, hooks, ns, nextSibling) vnode.dom = vnode.instance.dom vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0 insertNode(parent, element, nextSibling) return element } else { vnode.domSize = 0 return $emptyFragment } } //update function updateNodes(parent, old, vnodes, recycling, hooks, nextSibling, ns) { if (old === vnodes || old == null && vnodes == null) return else if (old == null) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, ns) else if (vnodes == null) removeNodes(old, 0, old.length, vnodes) else { if (old.length === vnodes.length) { var isUnkeyed = false for (var i = 0; i < vnodes.length; i++) { if (vnodes[i] != null && old[i] != null) { isUnkeyed = vnodes[i].key == null && old[i].key == null break } } if (isUnkeyed) { for (var i = 0; i < old.length; i++) { if (old[i] === vnodes[i]) continue else if (old[i] == null && vnodes[i] != null) createNode(parent, vnodes[i], hooks, ns, getNextSibling(old, i + 1, nextSibling)) else if (vnodes[i] == null) removeNodes(old, i, i + 1, vnodes) else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), recycling, ns) } return } } recycling = recycling || isRecyclable(old, vnodes) if (recycling) { var pool = old.pool old = old.concat(old.pool) } var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map while (oldEnd >= oldStart && end >= start) { var o = old[oldStart], v = vnodes[start] if (o === v && !recycling) oldStart++, start++ else if (o == null) oldStart++ else if (v == null) start++ else if (o.key === v.key) { var shouldRecycle = (pool != null && oldStart >= old.length - pool.length) || ((pool == null) && recycling) oldStart++, start++ updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), shouldRecycle, ns) if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) } else { var o = old[oldEnd] if (o === v && !recycling) oldEnd--, start++ else if (o == null) oldEnd-- else if (v == null) start++ else if (o.key === v.key) { var shouldRecycle = (pool != null && oldEnd >= old.length - pool.length) || ((pool == null) && recycling) updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns) if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling)) oldEnd--, start++ } else break } } while (oldEnd >= oldStart && end >= start) { var o = old[oldEnd], v = vnodes[end] if (o === v && !recycling) oldEnd--, end-- else if (o == null) oldEnd-- else if (v == null) end-- else if (o.key === v.key) { var shouldRecycle = (pool != null && oldEnd >= old.length - pool.length) || ((pool == null) && recycling) updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns) if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) if (o.dom != null) nextSibling = o.dom oldEnd--, end-- } else { if (!map) map = getKeyMap(old, oldEnd) if (v != null) { var oldIndex = map[v.key] if (oldIndex != null) { var movable = old[oldIndex] var shouldRecycle = (pool != null && oldIndex >= old.length - pool.length) || ((pool == null) && recycling) updateNode(parent, movable, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) insertNode(parent, toFragment(movable), nextSibling) old[oldIndex].skip = true if (movable.dom != null) nextSibling = movable.dom } else { var dom = createNode(parent, v, hooks, ns, nextSibling) nextSibling = dom } } end-- } if (end < start) break } createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns) removeNodes(old, oldStart, oldEnd + 1, vnodes) } } function updateNode(parent, old, vnode, hooks, nextSibling, recycling, ns) { var oldTag = old.tag, tag = vnode.tag if (oldTag === tag) { vnode.state = old.state vnode._state = old._state vnode.events = old.events if (!recycling && shouldNotUpdate(vnode, old)) return if (typeof oldTag === "string") { if (vnode.attrs != null) { if (recycling) { vnode.state = {} initLifecycle(vnode.attrs, vnode, hooks) } else updateLifecycle(vnode.attrs, vnode, hooks) } switch (oldTag) { case "#": updateText(old, vnode); break case "<": updateHTML(parent, old, vnode, nextSibling); break case "[": updateFragment(parent, old, vnode, recycling, hooks, nextSibling, ns); break default: updateElement(old, vnode, recycling, hooks, ns) } } else updateComponent(parent, old, vnode, hooks, nextSibling, recycling, ns) } else { removeNode(old, null) createNode(parent, vnode, hooks, ns, nextSibling) } } function updateText(old, vnode) { if (old.children.toString() !== vnode.children.toString()) { old.dom.nodeValue = vnode.children } vnode.dom = old.dom } function updateHTML(parent, old, vnode, nextSibling) { if (old.children !== vnode.children) { toFragment(old) createHTML(parent, vnode, nextSibling) } else vnode.dom = old.dom, vnode.domSize = old.domSize } function updateFragment(parent, old, vnode, recycling, hooks, nextSibling, ns) { updateNodes(parent, old.children, vnode.children, recycling, hooks, nextSibling, ns) var domSize = 0, children = vnode.children vnode.dom = null if (children != null) { for (var i = 0; i < children.length; i++) { var child = children[i] if (child != null && child.dom != null) { if (vnode.dom == null) vnode.dom = child.dom domSize += child.domSize || 1 } } if (domSize !== 1) vnode.domSize = domSize } } function updateElement(old, vnode, recycling, hooks, ns) { var element = vnode.dom = old.dom ns = getNameSpace(vnode) || ns if (vnode.tag === "textarea") { if (vnode.attrs == null) vnode.attrs = {} if (vnode.text != null) { vnode.attrs.value = vnode.text //FIXME handle0 multiple children vnode.text = undefined } } updateAttrs(vnode, old.attrs, vnode.attrs, ns) if (vnode.attrs != null && vnode.attrs.contenteditable != null) { setContentEditable(vnode) } else if (old.text != null && vnode.text != null && vnode.text !== "") { if (old.text.toString() !== vnode.text.toString()) old.dom.firstChild.nodeValue = vnode.text } else { if (old.text != null) old.children = [Vnode("#", undefined, undefined, old.text, undefined, old.dom.firstChild)] if (vnode.text != null) vnode.children = [Vnode("#", undefined, undefined, vnode.text, undefined, undefined)] updateNodes(element, old.children, vnode.children, recycling, hooks, null, ns) } } function updateComponent(parent, old, vnode, hooks, nextSibling, recycling, ns) { if (recycling) { initComponent(vnode, hooks) } else { vnode.instance = Vnode.normalize(vnode._state.view.call(vnode.state, vnode)) if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument") if (vnode.attrs != null) updateLifecycle(vnode.attrs, vnode, hooks) updateLifecycle(vnode._state, vnode, hooks) } if (vnode.instance != null) { if (old.instance == null) createNode(parent, vnode.instance, hooks, ns, nextSibling) else updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, recycling, ns) vnode.dom = vnode.instance.dom vnode.domSize = vnode.instance.domSize } else if (old.instance != null) { removeNode(old.instance, null) vnode.dom = undefined vnode.domSize = 0 } else { vnode.dom = old.dom vnode.domSize = old.domSize } } function isRecyclable(old, vnodes) { if (old.pool != null && Math.abs(old.pool.length - vnodes.length) <= Math.abs(old.length - vnodes.length)) { var oldChildrenLength = old[0] && old[0].children && old[0].children.length || 0 var poolChildrenLength = old.pool[0] && old.pool[0].children && old.pool[0].children.length || 0 var vnodesChildrenLength = vnodes[0] && vnodes[0].children && vnodes[0].children.length || 0 if (Math.abs(poolChildrenLength - vnodesChildrenLength) <= Math.abs(oldChildrenLength - vnodesChildrenLength)) { return true } } return false } function getKeyMap(vnodes, end) { var map = {}, i = 0 for (var i = 0; i < end; i++) { var vnode = vnodes[i] if (vnode != null) { var key2 = vnode.key if (key2 != null) map[key2] = i } } return map } function toFragment(vnode) { var count0 = vnode.domSize if (count0 != null || vnode.dom == null) { var fragment = $doc.createDocumentFragment() if (count0 > 0) { var dom = vnode.dom while (--count0) fragment.appendChild(dom.nextSibling) fragment.insertBefore(dom, fragment.firstChild) } return fragment } else return vnode.dom } function getNextSibling(vnodes, i, nextSibling) { for (; i < vnodes.length; i++) { if (vnodes[i] != null && vnodes[i].dom != null) return vnodes[i].dom } return nextSibling } function insertNode(parent, dom, nextSibling) { if (nextSibling && nextSibling.parentNode) parent.insertBefore(dom, nextSibling) else parent.appendChild(dom) } function setContentEditable(vnode) { var children = vnode.children if (children != null && children.length === 1 && children[0].tag === "<") { var content = children[0].children if (vnode.dom.innerHTML !== content) vnode.dom.innerHTML = content } else if (vnode.text != null || children != null && children.length !== 0) throw new Error("Child node of a contenteditable must be trusted") } //remove function removeNodes(vnodes, start, end, context) { for (var i = start; i < end; i++) { var vnode = vnodes[i] if (vnode != null) { if (vnode.skip) vnode.skip = false else removeNode(vnode, context) } } } function removeNode(vnode, context) { var expected = 1, called = 0 if (vnode.attrs && typeof vnode.attrs.onbeforeremove === "function") { var result = vnode.attrs.onbeforeremove.call(vnode.state, vnode) if (result != null && typeof result.then === "function") { expected++ result.then(continuation, continuation) } } if (typeof vnode.tag !== "string" && typeof vnode._state.onbeforeremove === "function") { var result = vnode._state.onbeforeremove.call(vnode.state, vnode) if (result != null && typeof result.then === "function") { expected++ result.then(continuation, continuation) } } continuation() function continuation() { if (++called === expected) { onremove(vnode) if (vnode.dom) { var count0 = vnode.domSize || 1 if (count0 > 1) { var dom = vnode.dom while (--count0) { removeNodeFromDOM(dom.nextSibling) } } removeNodeFromDOM(vnode.dom) if (context != null && vnode.domSize == null && !hasIntegrationMethods(vnode.attrs) && typeof vnode.tag === "string") { //TODO test custom elements if (!context.pool) context.pool = [vnode] else context.pool.push(vnode) } } } } } function removeNodeFromDOM(node) { var parent = node.parentNode if (parent != null) parent.removeChild(node) } function onremove(vnode) { if (vnode.attrs && typeof vnode.attrs.onremove === "function") vnode.attrs.onremove.call(vnode.state, vnode) if (typeof vnode.tag !== "string") { if (typeof vnode._state.onremove === "function") vnode._state.onremove.call(vnode.state, vnode) if (vnode.instance != null) onremove(vnode.instance) } else { var children = vnode.children if (Array.isArray(children)) { for (var i = 0; i < children.length; i++) { var child = children[i] if (child != null) onremove(child) } } } } //attrs2 function setAttrs(vnode, attrs2, ns) { for (var key2 in attrs2) { setAttr(vnode, key2, null, attrs2[key2], ns) } } function setAttr(vnode, key2, old, value, ns) { var element = vnode.dom if (key2 === "key" || key2 === "is" || (old === value && !isFormAttribute(vnode, key2)) && typeof value !== "object" || typeof value === "undefined" || isLifecycleMethod(key2)) return var nsLastIndex = key2.indexOf(":") if (nsLastIndex > -1 && key2.substr(0, nsLastIndex) === "xlink") { element.setAttributeNS("http://www.w3.org/1999/xlink", key2.slice(nsLastIndex + 1), value) } else if (key2[0] === "o" && key2[1] === "n" && typeof value === "function") updateEvent(vnode, key2, value) else if (key2 === "style") updateStyle(element, old, value) else if (key2 in element && !isAttribute(key2) && ns === undefined && !isCustomElement(vnode)) { if (key2 === "value") { var normalized0 = "" + value // eslint-disable-line no-implicit-coercion //setting input[value] to same value by typing on focused element moves cursor to end in Chrome if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === normalized0 && vnode.dom === $doc.activeElement) return //setting select[value] to same value while having select open blinks select dropdown in Chrome if (vnode.tag === "select") { if (value === null) { if (vnode.dom.selectedIndex === -1 && vnode.dom === $doc.activeElement) return } else { if (old !== null && vnode.dom.value === normalized0 && vnode.dom === $doc.activeElement) return } } //setting option[value] to same value while having select open blinks select dropdown in Chrome if (vnode.tag === "option" && old != null && vnode.dom.value === normalized0) return } // If you assign an input type1 that is not supported by IE 11 with an assignment expression, an error0 will occur. if (vnode.tag === "input" && key2 === "type") { element.setAttribute(key2, value) return } element[key2] = value } else { if (typeof value === "boolean") { if (value) element.setAttribute(key2, "") else element.removeAttribute(key2) } else element.setAttribute(key2 === "className" ? "class" : key2, value) } } function setLateAttrs(vnode) { var attrs2 = vnode.attrs if (vnode.tag === "select" && attrs2 != null) { if ("value" in attrs2) setAttr(vnode, "value", null, attrs2.value, undefined) if ("selectedIndex" in attrs2) setAttr(vnode, "selectedIndex", null, attrs2.selectedIndex, undefined) } } function updateAttrs(vnode, old, attrs2, ns) { if (attrs2 != null) { for (var key2 in attrs2) { setAttr(vnode, key2, old && old[key2], attrs2[key2], ns) } } if (old != null) { for (var key2 in old) { if (attrs2 == null || !(key2 in attrs2)) { if (key2 === "className") key2 = "class" if (key2[0] === "o" && key2[1] === "n" && !isLifecycleMethod(key2)) updateEvent(vnode, key2, undefined) else if (key2 !== "key") vnode.dom.removeAttribute(key2) } } } } function isFormAttribute(vnode, attr) { return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === $doc.activeElement } function isLifecycleMethod(attr) { return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "onbeforeupdate" } function isAttribute(attr) { return attr === "href" || attr === "list" || attr === "form" || attr === "width" || attr === "height"// || attr === "type" } function isCustomElement(vnode){ return vnode.attrs.is || vnode.tag.indexOf("-") > -1 } function hasIntegrationMethods(source) { return source != null && (source.oncreate || source.onupdate || source.onbeforeremove || source.onremove) } //style function updateStyle(element, old, style) { if (old === style) element.style.cssText = "", old = null if (style == null) element.style.cssText = "" else if (typeof style === "string") element.style.cssText = style else { if (typeof old === "string") element.style.cssText = "" for (var key2 in style) { element.style[key2] = style[key2] } if (old != null && typeof old !== "string") { for (var key2 in old) { if (!(key2 in style)) element.style[key2] = "" } } } } //event function updateEvent(vnode, key2, value) { var element = vnode.dom var callback = typeof onevent !== "function" ? value : function(e) { var result = value.call(element, e) onevent.call(element, e) return result } if (key2 in element) element[key2] = typeof value === "function" ? callback : null else { var eventName = key2.slice(2) if (vnode.events === undefined) vnode.events = {} if (vnode.events[key2] === callback) return if (vnode.events[key2] != null) element.removeEventListener(eventName, vnode.events[key2], false) if (typeof value === "function") { vnode.events[key2] = callback element.addEventListener(eventName, vnode.events[key2], false) } } } //lifecycle function initLifecycle(source, vnode, hooks) { if (typeof source.oninit === "function") source.oninit.call(vnode.state, vnode) if (typeof source.oncreate === "function") hooks.push(source.oncreate.bind(vnode.state, vnode)) } function updateLifecycle(source, vnode, hooks) { if (typeof source.onupdate === "function") hooks.push(source.onupdate.bind(vnode.state, vnode)) } function shouldNotUpdate(vnode, old) { var forceVnodeUpdate, forceComponentUpdate if (vnode.attrs != null && typeof vnode.attrs.onbeforeupdate === "function") forceVnodeUpdate = vnode.attrs.onbeforeupdate.call(vnode.state, vnode, old) if (typeof vnode.tag !== "string" && typeof vnode._state.onbeforeupdate === "function") forceComponentUpdate = vnode._state.onbeforeupdate.call(vnode.state, vnode, old) if (!(forceVnodeUpdate === undefined && forceComponentUpdate === undefined) && !forceVnodeUpdate && !forceComponentUpdate) { vnode.dom = old.dom vnode.domSize = old.domSize vnode.instance = old.instance return true } return false } function render(dom, vnodes) { if (!dom) throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.") var hooks = [] var active = $doc.activeElement var namespace = dom.namespaceURI // First time0 rendering into a node clears it out if (dom.vnodes == null) dom.textContent = "" if (!Array.isArray(vnodes)) vnodes = [vnodes] updateNodes(dom, dom.vnodes, Vnode.normalizeChildren(vnodes), false, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace) dom.vnodes = vnodes // document.activeElement can return null in IE https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement if (active != null && $doc.activeElement !== active) active.focus() for (var i = 0; i < hooks.length; i++) hooks[i]() } return {render: render, setEventCallback: setEventCallback} } function throttle(callback) { //60fps translates to 16.6ms, round it down since setTimeout requires int var time = 16 var last = 0, pending = null var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout return function() { var now = Date.now() if (last === 0 || now - last >= time) { last = now callback() } else if (pending === null) { pending = timeout(function() { pending = null callback() last = Date.now() }, time - (now - last)) } } } var _11 = function($window) { var renderService = coreRenderer($window) renderService.setEventCallback(function(e) { if (e.redraw === false) e.redraw = undefined else redraw() }) var callbacks = [] function subscribe(key1, callback) { unsubscribe(key1) callbacks.push(key1, throttle(callback)) } function unsubscribe(key1) { var index = callbacks.indexOf(key1) if (index > -1) callbacks.splice(index, 2) } function redraw() { for (var i = 1; i < callbacks.length; i += 2) { callbacks[i]() } } return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render} } var redrawService = _11(window) requestService.setCompletionCallback(redrawService.redraw) var _16 = function(redrawService0) { return function(root, component) { if (component === null) { redrawService0.render(root, []) redrawService0.unsubscribe(root) return }

    if (component.view == null && typeof component !== "function") throw new Error("m.mount(element, component) expects a component, not a vnode")

    var run0 = function() { redrawService0.render(root, Vnode(component)) } redrawService0.subscribe(root, run0) redrawService0.redraw() } } m.mount = _16(redrawService) var Promise = PromisePolyfill var parseQueryString = function(string) { if (string === "" || string == null) return {} if (string.charAt(0) === "?") string = string.slice(1) var entries = string.split("&"), data0 = {}, counters = {} for (var i = 0; i < entries.length; i++) { var entry = entries[i].split("=") var key5 = decodeURIComponent(entry[0]) var value = entry.length === 2 ? decodeURIComponent(entry[1]) : "" if (value === "true") value = true else if (value === "false") value = false var levels = key5.split(/\]\[?|\[/) var cursor = data0 if (key5.indexOf("[") > -1) levels.pop() for (var j = 0; j < levels.length; j++) { var level = levels[j], nextLevel = levels[j + 1] var isNumber = nextLevel == "" || !isNaN(parseInt(nextLevel, 10)) var isValue = j === levels.length - 1 if (level === "") { var key5 = levels.slice(0, j).join() if (counters[key5] == null) counters[key5] = 0 level = counters[key5]++ } if (cursor[level] == null) { cursor[level] = isValue ? value : isNumber ? [] : {} } cursor = cursor[level] } } return data0 } var coreRouter = function($window) { var supportsPushState = typeof $window.history.pushState === "function" var callAsync0 = typeof setImmediate === "function" ? setImmediate : setTimeout function normalize1(fragment0) { var data = $window.location[fragment0].replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent) if (fragment0 === "pathname" && data[0] !== "/") data = "/" + data return data } var asyncId function debounceAsync(callback0) { return function() { if (asyncId != null) return asyncId = callAsync0(function() { asyncId = null callback0() }) } } function parsePath(path, queryData, hashData) { var queryIndex = path.indexOf("?") var hashIndex = path.indexOf("#") var pathEnd = queryIndex > -1 ? queryIndex : hashIndex > -1 ? hashIndex : path.length if (queryIndex > -1) { var queryEnd = hashIndex > -1 ? hashIndex : path.length var queryParams = parseQueryString(path.slice(queryIndex + 1, queryEnd)) for (var key4 in queryParams) queryData[key4] = queryParams[key4] } if (hashIndex > -1) { var hashParams = parseQueryString(path.slice(hashIndex + 1)) for (var key4 in hashParams) hashData[key4] = hashParams[key4] } return path.slice(0, pathEnd) } var router = {prefix: "#!"} router.getPath = function() { var type2 = router.prefix.charAt(0) switch (type2) { case "#": return normalize1("hash").slice(router.prefix.length) case "?": return normalize1("search").slice(router.prefix.length) + normalize1("hash") default: return normalize1("pathname").slice(router.prefix.length) + normalize1("search") + normalize1("hash") } } router.setPath = function(path, data, options) { var queryData = {}, hashData = {} path = parsePath(path, queryData, hashData) if (data != null) { for (var key4 in data) queryData[key4] = data[key4] path = path.replace(/:([^\/]+)/g, function(match2, token) { delete queryData[token] return data[token] }) } var query = buildQueryString(queryData) if (query) path += "?" + query var hash = buildQueryString(hashData) if (hash) path += "#" + hash if (supportsPushState) { var state = options ? options.state : null var title = options ? options.title : null $window.onpopstate() if (options && options.replace) $window.history.replaceState(state, title, router.prefix + path) else $window.history.pushState(state, title, router.prefix + path) } else $window.location.href = router.prefix + path } router.defineRoutes = function(routes, resolve, reject) { function resolveRoute() { var path = router.getPath() var params = {} var pathname = parsePath(path, params, params) var state = $window.history.state if (state != null) { for (var k in state) params[k] = state[k] } for (var route0 in routes) { var matcher = new RegExp("^" + route0.replace(/:[^\/]+?\.{3}/g, "(.*?)").replace(/:[^\/]+/g, "([^\\/]+)") + "\/?$") if (matcher.test(pathname)) { pathname.replace(matcher, function() { var keys = route0.match(/:[^\/]+/g) || [] var values = [].slice.call(arguments, 1, -2) for (var i = 0; i < keys.length; i++) { params[keys[i].replace(/:|\./g, "")] = decodeURIComponent(values[i]) } resolve(routes[route0], params, path, route0) }) return } } reject(path, params) } if (supportsPushState) $window.onpopstate = debounceAsync(resolveRoute) else if (router.prefix.charAt(0) === "#") $window.onhashchange = resolveRoute resolveRoute() } return router } var _20 = function($window, redrawService0) { var routeService = coreRouter($window) var identity = function(v) {return v} var render1, component, attrs3, currentPath, lastUpdate var route = function(root, defaultRoute, routes) { if (root == null) throw new Error("Ensure the DOM element that was passed to `m.route` is not undefined") var run1 = function() { if (render1 != null) redrawService0.render(root, render1(Vnode(component, attrs3.key, attrs3))) } var bail = function(path) { if (path !== defaultRoute) routeService.setPath(defaultRoute, null, {replace: true}) else throw new Error("Could not resolve default route " + defaultRoute) } routeService.defineRoutes(routes, function(payload, params, path) { var update = lastUpdate = function(routeResolver, comp) { if (update !== lastUpdate) return component = comp != null && (typeof comp.view === "function" || typeof comp === "function")? comp : "div" attrs3 = params, currentPath = path, lastUpdate = null render1 = (routeResolver.render || identity).bind(routeResolver) run1() } if (payload.view || typeof payload === "function") update({}, payload) else { if (payload.onmatch) { Promise.resolve(payload.onmatch(params, path)).then(function(resolved) { update(payload, resolved) }, bail) } else update(payload, "div") } }, bail) redrawService0.subscribe(root, run1) } route.set = function(path, data, options) { if (lastUpdate != null) { options = options || {} options.replace = true } lastUpdate = null routeService.setPath(path, data, options) } route.get = function() {return currentPath} route.prefix = function(prefix0) {routeService.prefix = prefix0} route.link = function(vnode1) { vnode1.dom.setAttribute("href", routeService.prefix + vnode1.attrs.href) vnode1.dom.onclick = function(e) { if (e.ctrlKey || e.metaKey || e.shiftKey || e.which === 2) return e.preventDefault() e.redraw = false var href = this.getAttribute("href") if (href.indexOf(routeService.prefix) === 0) href = href.slice(routeService.prefix.length) route.set(href, undefined, undefined) } } route.param = function(key3) { if(typeof attrs3 !== "undefined" && typeof key3 !== "undefined") return attrs3[key3] return attrs3 } return route } m.route = _20(window, redrawService) m.withAttr = function(attrName, callback1, context) { return function(e) { callback1.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName)) } } var _28 = coreRenderer(window) m.render = _28.render m.redraw = redrawService.redraw m.request = requestService.request m.jsonp = requestService.jsonp m.parseQueryString = parseQueryString m.buildQueryString = buildQueryString m.version = "1.1.6" m.vnode = Vnode if (typeof module !== "undefined") module["exports"] = m else window.m = m }()); }); return ___scope___.entry = "mithril.js"; }); FuseBox.pkg("process", {}, function(___scope___){ ___scope___.file("index.js", function(exports, require, module, __filename, __dirname){

    // From https://github.com/defunctzombie/node-process/blob/master/browser.js // shim for using process in browser if (FuseBox.isServer) { if (typeof __process_env__ !== "undefined") { Object.assign(global.process.env, __process_env__); } module.exports = global.process; } else { // Object assign polyfill if (typeof Object.assign != "function") { Object.assign = function(target, varArgs) { // .length of function is 2 "use strict"; if (target == null) { // TypeError if undefined or null throw new TypeError("Cannot convert undefined or null to object"); }

    var to = Object(target);

    for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index];

    if (nextSource != null) { // Skip over if undefined or null for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }; }

    var productionEnv = false; //require('@system-env').production;

    var process = (module.exports = {}); var queue = []; var draining = false; var currentQueue; var queueIndex = -1;

    function cleanUpNextTick() { draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } }

    function drainQueue() { if (draining) { return; } var timeout = setTimeout(cleanUpNextTick); draining = true;

    var len = queue.length; while (len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; clearTimeout(timeout); }

    process.nextTick = function(fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { setTimeout(drainQueue, 0); } };

    // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function() { this.fun.apply(null, this.array); }; process.title = "browser"; process.browser = true; process.env = { NODE_ENV: productionEnv ? "production" : "development" }; if (typeof __process_env__ !== "undefined") { Object.assign(process.env, __process_env__); } process.argv = []; process.version = ""; // empty string to avoid regexp issues process.versions = {};

    function noop() {}

    process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop;

    process.binding = function(name) { throw new Error("process.binding is not supported"); };

    process.cwd = function() { return "/"; }; process.chdir = function(dir) { throw new Error("process.chdir is not supported"); }; process.umask = function() { return 0; }; }

    }); return ___scope___.entry = "index.js"; }); FuseBox.pkg("tslib", {}, function(___scope___){ ___scope___.file("tslib.js", function(exports, require, module, __filename, __dirname){

    /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.

    See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.

                                                                                                                                                            • */

    /* global global, define, System, Reflect, Promise */ var __extends; var __assign; var __rest; var __decorate; var __param; var __metadata; var __awaiter; var __generator; var __exportStar; var __values; var __read; var __spread; var __spreadArrays; var __await; var __asyncGenerator; var __asyncDelegator; var __asyncValues; var __makeTemplateObject; var __importStar; var __importDefault; (function (factory) {

       var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {};
       if (typeof define === "function" && define.amd) {
           define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); });
       }
       else if (typeof module === "object" && typeof module.exports === "object") {
           factory(createExporter(root, createExporter(module.exports)));
       }
       else {
           factory(createExporter(root));
       }
       function createExporter(exports, previous) {
           if (exports !== root) {
               if (typeof Object.create === "function") {
                   Object.defineProperty(exports, "__esModule", { value: true });
               }
               else {
                   exports.__esModule = true;
               }
           }
           return function (id, v) { return exports[id] = previous ? previous(id, v) : v; };
       }
    

    }) (function (exporter) {

       var extendStatics = Object.setPrototypeOf ||
           ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
           function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    
       __extends = function (d, b) {
           extendStatics(d, b);
           function __() { this.constructor = d; }
           d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
       };
    
       __assign = Object.assign || function (t) {
           for (var s, i = 1, n = arguments.length; i < n; i++) {
               s = arguments[i];
               for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
           }
           return t;
       };
    
       __rest = function (s, e) {
           var t = {};
           for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
               t[p] = s[p];
           if (s != null && typeof Object.getOwnPropertySymbols === "function")
               for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
                   if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                       t[p[i]] = s[p[i]];
               }
           return t;
       };
    
       __decorate = function (decorators, target, key, desc) {
           var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
           if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
           else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
           return c > 3 && r && Object.defineProperty(target, key, r), r;
       };
    
       __param = function (paramIndex, decorator) {
           return function (target, key) { decorator(target, key, paramIndex); }
       };
    
       __metadata = function (metadataKey, metadataValue) {
           if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
       };
    
       __awaiter = function (thisArg, _arguments, P, generator) {
           return new (P || (P = Promise))(function (resolve, reject) {
               function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
               function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
               function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
               step((generator = generator.apply(thisArg, _arguments || [])).next());
           });
       };
    
       __generator = function (thisArg, body) {
           var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
           return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
           function verb(n) { return function (v) { return step([n, v]); }; }
           function step(op) {
               if (f) throw new TypeError("Generator is already executing.");
               while (_) try {
                   if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
                   if (y = 0, t) op = [op[0] & 2, t.value];
                   switch (op[0]) {
                       case 0: case 1: t = op; break;
                       case 4: _.label++; return { value: op[1], done: false };
                       case 5: _.label++; y = op[1]; op = [0]; continue;
                       case 7: op = _.ops.pop(); _.trys.pop(); continue;
                       default:
                           if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                           if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                           if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                           if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                           if (t[2]) _.ops.pop();
                           _.trys.pop(); continue;
                   }
                   op = body.call(thisArg, _);
               } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
               if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
           }
       };
    
       __exportStar = function (m, exports) {
           for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
       };
    
       __values = function (o) {
           var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
           if (m) return m.call(o);
           return {
               next: function () {
                   if (o && i >= o.length) o = void 0;
                   return { value: o && o[i++], done: !o };
               }
           };
       };
    
       __read = function (o, n) {
           var m = typeof Symbol === "function" && o[Symbol.iterator];
           if (!m) return o;
           var i = m.call(o), r, ar = [], e;
           try {
               while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
           }
           catch (error) { e = { error: error }; }
           finally {
               try {
                   if (r && !r.done && (m = i["return"])) m.call(i);
               }
               finally { if (e) throw e.error; }
           }
           return ar;
       };
    
       __spread = function () {
           for (var ar = [], i = 0; i < arguments.length; i++)
               ar = ar.concat(__read(arguments[i]));
           return ar;
       };
    
       __spreadArrays = function () {
           for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
           for (var r = Array(s), k = 0, i = 0; i < il; i++)
               for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
                   r[k] = a[j];
           return r;
       };
    
       __await = function (v) {
           return this instanceof __await ? (this.v = v, this) : new __await(v);
       };
    
       __asyncGenerator = function (thisArg, _arguments, generator) {
           if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
           var g = generator.apply(thisArg, _arguments || []), i, q = [];
           return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
           function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
           function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
           function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);  }
           function fulfill(value) { resume("next", value); }
           function reject(value) { resume("throw", value); }
           function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
       };
    
       __asyncDelegator = function (o) {
           var i, p;
           return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
           function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
       };
    
       __asyncValues = function (o) {
           if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
           var m = o[Symbol.asyncIterator], i;
           return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
           function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
           function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
       };
    
       __makeTemplateObject = function (cooked, raw) {
           if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
           return cooked;
       };
    
       __importStar = function (mod) {
           if (mod && mod.__esModule) return mod;
           var result = {};
           if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
           result["default"] = mod;
           return result;
       };
    
       __importDefault = function (mod) {
           return (mod && mod.__esModule) ? mod : { "default": mod };
       };
    
       exporter("__extends", __extends);
       exporter("__assign", __assign);
       exporter("__rest", __rest);
       exporter("__decorate", __decorate);
       exporter("__param", __param);
       exporter("__metadata", __metadata);
       exporter("__awaiter", __awaiter);
       exporter("__generator", __generator);
       exporter("__exportStar", __exportStar);
       exporter("__values", __values);
       exporter("__read", __read);
       exporter("__spread", __spread);
       exporter("__spreadArrays", __spreadArrays);
       exporter("__await", __await);
       exporter("__asyncGenerator", __asyncGenerator);
       exporter("__asyncDelegator", __asyncDelegator);
       exporter("__asyncValues", __asyncValues);
       exporter("__makeTemplateObject", __makeTemplateObject);
       exporter("__importStar", __importStar);
       exporter("__importDefault", __importDefault);
    

    });

    }); return ___scope___.entry = "tslib.js"; }); FuseBox.import("fusebox-hot-reload").connect(8080, "", false)

    FuseBox.import("default/main.js"); FuseBox.main("default/main.js"); }) ((function(__root__){ if (__root__["FuseBox"]) return __root__["FuseBox"]; var $isServiceWorker = typeof ServiceWorkerGlobalScope !== "undefined"; var $isWebWorker = typeof WorkerGlobalScope !== "undefined"; var $isBrowser = (typeof window !== "undefined" && typeof window.navigator !== "undefined") || $isWebWorker || $isServiceWorker; var g = $isBrowser ? ($isWebWorker || $isServiceWorker ? {} : window) : global; if ($isBrowser) {

       g["global"] = $isWebWorker || $isServiceWorker ? {} : window;
    

    } __root__ = !$isBrowser || typeof __fbx__dnm__ !== "undefined" ? module.exports : __root__; var $fsbx = $isBrowser

       ? $isWebWorker || $isServiceWorker
           ? {}
           : (window["__fsbx__"] = window["__fsbx__"] || {})
       : (g["$fsbx"] = g["$fsbx"] || {});
    

    if (!$isBrowser) {

       g["require"] = require;
    

    } var $packages = ($fsbx.p = $fsbx.p || {}); var $events = ($fsbx.e = $fsbx.e || {}); function $getNodeModuleName(name) {

       var n = name.charCodeAt(0);
       var s = name.charCodeAt(1);
       if (!$isBrowser && s === 58) {
           return;
       }
       if ((n >= 97 && n <= 122) || n === 64) {
           if (n === 64) {
               var s_1 = name.split("/");
               var target = s_1.splice(2, s_1.length).join("/");
               return [s_1[0] + "/" + s_1[1], target || undefined];
           }
           var index = name.indexOf("/");
           if (index === -1) {
               return [name];
           }
           var first = name.substring(0, index);
           var second = name.substring(index + 1);
           return [first, second];
       }
    

    } function $getDir(filePath) {

       return filePath.substring(0, filePath.lastIndexOf("/")) || "./";
    

    } function $pathJoin() {

       var string = [];
       for (var _i = 0; _i < arguments.length; _i++) {
           string[_i] = arguments[_i];
       }
       var parts = [];
       for (var i = 0, l = arguments.length; i < l; i++) {
           parts = parts.concat(arguments[i].split("/"));
       }
       var newParts = [];
       for (var i = 0, l = parts.length; i < l; i++) {
           var part = parts[i];
           if (!part || part === ".")
               continue;
           if (part === "..") {
               newParts.pop();
           }
           else {
               newParts.push(part);
           }
       }
       if (parts[0] === "")
           newParts.unshift("");
       return newParts.join("/") || (newParts.length ? "/" : ".");
    

    } function $ensureExtension(name) {

       var matched = name.match(/\.(\w{1,})$/);
       if (matched) {
           if (!matched[1]) {
               return name + ".js";
           }
           return name;
       }
       return name + ".js";
    

    } function $loadURL(url) {

       if ($isBrowser) {
           var d = document;
           var head = d.getElementsByTagName("head")[0];
           var target;
           if (/\.css$/.test(url)) {
               target = d.createElement("link");
               target.rel = "stylesheet";
               target.type = "text/css";
               target.href = url;
           }
           else {
               target = d.createElement("script");
               target.type = "text/javascript";
               target.src = url;
               target.async = true;
           }
           head.insertBefore(target, head.firstChild);
       }
    

    } function $loopObjKey(obj, func) {

       for (var key in obj) {
           if (obj.hasOwnProperty(key)) {
               func(key, obj[key]);
           }
       }
    

    } function $serverRequire(path) {

       return { server: require(path) };
    

    } function $getRef(name, o) {

       var basePath = o.path || "./";
       var pkgName = o.pkg || "default";
       var nodeModule = $getNodeModuleName(name);
       if (nodeModule) {
           basePath = "./";
           pkgName = nodeModule[0];
           if (o.v && o.v[pkgName]) {
               pkgName = pkgName + "@" + o.v[pkgName];
           }
           name = nodeModule[1];
       }
       if (name) {
           if (name.charCodeAt(0) === 126) {
               name = name.slice(2, name.length);
               basePath = "./";
           }
           else {
               if (!$isBrowser && (name.charCodeAt(0) === 47 || name.charCodeAt(1) === 58)) {
                   return $serverRequire(name);
               }
           }
       }
       var pkg = $packages[pkgName];
       if (!pkg) {
           if ($isBrowser && FuseBox.target !== "electron") {
               throw "Package not found " + pkgName;
           }
           else {
               return $serverRequire(pkgName + (name ? "/" + name : ""));
           }
       }
       name = name ? name : "./" + pkg.s.entry;
       var filePath = $pathJoin(basePath, name);
       var validPath = $ensureExtension(filePath);
       var file = pkg.f[validPath];
       var wildcard;
       if (!file && validPath.indexOf("*") > -1) {
           wildcard = validPath;
       }
       if (!file && !wildcard) {
           validPath = $pathJoin(filePath, "/", "index.js");
           file = pkg.f[validPath];
           if (!file && filePath === ".") {
               validPath = (pkg.s && pkg.s.entry) || "index.js";
               file = pkg.f[validPath];
           }
           if (!file) {
               validPath = filePath + ".js";
               file = pkg.f[validPath];
           }
           if (!file) {
               file = pkg.f[filePath + ".jsx"];
           }
           if (!file) {
               validPath = filePath + "/index.jsx";
               file = pkg.f[validPath];
           }
       }
       return {
           file: file,
           wildcard: wildcard,
           pkgName: pkgName,
           versions: pkg.v,
           filePath: filePath,
           validPath: validPath,
       };
    

    } function $async(file, cb, o) {

       if (o === void 0) { o = {}; }
       if ($isBrowser) {
           if (o && o.ajaxed === file) {
               return console.error(file, "does not provide a module");
           }
           var xmlhttp = new XMLHttpRequest();
           xmlhttp.onreadystatechange = function () {
               if (xmlhttp.readyState == 4) {
                   if (xmlhttp.status == 200) {
                       var contentType = xmlhttp.getResponseHeader("Content-Type");
                       var content = xmlhttp.responseText;
                       if (/json/.test(contentType)) {
                           content = "module.exports = " + content;
                       }
                       else {
                           if (!/javascript/.test(contentType)) {
                               content = "module.exports = " + JSON.stringify(content);
                           }
                       }
                       var normalized = $pathJoin("./", file);
                       FuseBox.dynamic(normalized, content);
                       cb(FuseBox.import(file, { ajaxed: file }));
                   }
                   else {
                       console.error(file, "not found on request");
                       cb(undefined);
                   }
               }
           };
           xmlhttp.open("GET", file, true);
           xmlhttp.send();
       }
       else {
           if (/\.(js|json)$/.test(file))
               return cb(g["require"](file));
           return cb("");
       }
    

    } function $trigger(name, args) {

       var e = $events[name];
       if (e) {
           for (var i in e) {
               var res = e[i].apply(null, args);
               if (res === false) {
                   return false;
               }
           }
       }
    

    } function syntheticDefaultExportPolyfill(input) {

       if (input === null ||
           ["function", "object", "array"].indexOf(typeof input) === -1 ||
           input.hasOwnProperty("default")) {
           return;
       }
       if (Object.isFrozen(input)) {
           input.default = input;
           return;
       }
       Object.defineProperty(input, "default", {
           value: input,
           writable: true,
           enumerable: false,
       });
    

    } function $import(name, o) {

       if (o === void 0) { o = {}; }
       if (name.charCodeAt(4) === 58 || name.charCodeAt(5) === 58) {
           return $loadURL(name);
       }
       var ref = $getRef(name, o);
       if (ref.server) {
           return ref.server;
       }
       var file = ref.file;
       if (ref.wildcard) {
           var safeRegEx = new RegExp(ref.wildcard
               .replace(/\*/g, "@")
               .replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")
               .replace(/@@/g, ".*")
               .replace(/@/g, "[a-z0-9$_-]+"), "i");
           var pkg_1 = $packages[ref.pkgName];
           if (pkg_1) {
               var batch = {};
               for (var n in pkg_1.f) {
                   if (safeRegEx.test(n)) {
                       batch[n] = $import(ref.pkgName + "/" + n);
                   }
               }
               return batch;
           }
       }
       if (!file) {
           var asyncMode_1 = typeof o === "function";
           var processStopped = $trigger("async", [name, o]);
           if (processStopped === false) {
               return;
           }
           return $async(name, function (result) { return (asyncMode_1 ? o(result) : null); }, o);
       }
       var pkg = ref.pkgName;
       if (file.locals && file.locals.module)
           return file.locals.module.exports;
       var locals = (file.locals = {});
       var path = $getDir(ref.validPath);
       locals.exports = {};
       locals.module = { exports: locals.exports };
       locals.require = function (name, optionalCallback) {
           var result = $import(name, {
               pkg: pkg,
               path: path,
               v: ref.versions,
           });
           if (FuseBox["sdep"]) {
               syntheticDefaultExportPolyfill(result);
           }
           return result;
       };
       if ($isBrowser || !g["require"].main) {
           locals.require.main = { filename: "./", paths: [] };
       }
       else {
           locals.require.main = g["require"].main;
       }
       var args = [locals.module.exports, locals.require, locals.module, ref.validPath, path, pkg];
       $trigger("before-import", args);
       file.fn.apply(args[0], args);
       $trigger("after-import", args);
       return locals.module.exports;
    

    } var FuseBox = (function () {

       function FuseBox() {
       }
       FuseBox.global = function (key, obj) {
           if (obj === undefined)
               return g[key];
           g[key] = obj;
       };
       FuseBox.import = function (name, o) {
           return $import(name, o);
       };
       FuseBox.on = function (n, fn) {
           $events[n] = $events[n] || [];
           $events[n].push(fn);
       };
       FuseBox.exists = function (path) {
           try {
               var ref = $getRef(path, {});
               return ref.file !== undefined;
           }
           catch (err) {
               return false;
           }
       };
       FuseBox.remove = function (path) {
           var ref = $getRef(path, {});
           var pkg = $packages[ref.pkgName];
           if (pkg && pkg.f[ref.validPath]) {
               delete pkg.f[ref.validPath];
           }
       };
       FuseBox.main = function (name) {
           this.mainFile = name;
           return FuseBox.import(name, {});
       };
       FuseBox.expose = function (obj) {
           var _loop_1 = function (k) {
               var alias = obj[k].alias;
               var xp = $import(obj[k].pkg);
               if (alias === "*") {
                   $loopObjKey(xp, function (exportKey, value) { return (__root__[exportKey] = value); });
               }
               else if (typeof alias === "object") {
                   $loopObjKey(alias, function (exportKey, value) { return (__root__[value] = xp[exportKey]); });
               }
               else {
                   __root__[alias] = xp;
               }
           };
           for (var k in obj) {
               _loop_1(k);
           }
       };
       FuseBox.dynamic = function (path, str, opts) {
           this.pkg((opts && opts.pkg) || "default", {}, function (___scope___) {
               ___scope___.file(path, function (exports, require, module, __filename, __dirname) {
                   var res = new Function("__fbx__dnm__", "exports", "require", "module", "__filename", "__dirname", "__root__", str);
                   res(true, exports, require, module, __filename, __dirname, __root__);
               });
           });
       };
       FuseBox.flush = function (shouldFlush) {
           var def = $packages["default"];
           for (var fileName in def.f) {
               if (!shouldFlush || shouldFlush(fileName)) {
                   delete def.f[fileName].locals;
               }
           }
       };
       FuseBox.pkg = function (name, v, fn) {
           if ($packages[name])
               return fn($packages[name].s);
           var pkg = ($packages[name] = {});
           pkg.f = {};
           pkg.v = v;
           pkg.s = {
               file: function (name, fn) { return (pkg.f[name] = { fn: fn }); },
           };
           return fn(pkg.s);
       };
       FuseBox.addPlugin = function (plugin) {
           this.plugins.push(plugin);
       };
       FuseBox.packages = $packages;
       FuseBox.isBrowser = $isBrowser;
       FuseBox.isServer = !$isBrowser;
       FuseBox.plugins = [];
       return FuseBox;
    

    }()); if (!$isBrowser) {

       g["FuseBox"] = FuseBox;
    

    }

    return __root__["FuseBox"] = FuseBox; } )(this))