UNPKG

12.6 kBJavaScriptView Raw
1/**
2 * lodash 4.1.0 (Custom Build) <https://lodash.com/>
3 * Build: `lodash modularize exports="npm" -o ./`
4 * Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
5 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
6 * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
7 * Available under MIT license <https://lodash.com/license>
8 */
9var baseIsEqual = require('lodash._baseisequal'),
10 baseIsMatch = require('lodash._baseismatch'),
11 get = require('lodash.get'),
12 hasIn = require('lodash.hasin'),
13 root = require('lodash._root'),
14 toPairs = require('lodash.topairs');
15
16/** Used to compose bitmasks for comparison styles. */
17var UNORDERED_COMPARE_FLAG = 1,
18 PARTIAL_COMPARE_FLAG = 2;
19
20/** Used as references for various `Number` constants. */
21var INFINITY = 1 / 0;
22
23/** `Object#toString` result references. */
24var symbolTag = '[object Symbol]';
25
26/** Used to match property names within property paths. */
27var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
28 reIsPlainProp = /^\w*$/,
29 rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g;
30
31/** Used to match backslashes in property paths. */
32var reEscapeChar = /\\(\\)?/g;
33
34/**
35 * The base implementation of methods like `_.max` and `_.min` which accepts a
36 * `comparator` to determine the extremum value.
37 *
38 * @private
39 * @param {Array} array The array to iterate over.
40 * @param {Function} iteratee The iteratee invoked per iteration.
41 * @param {Function} comparator The comparator used to compare values.
42 * @returns {*} Returns the extremum value.
43 */
44function baseExtremum(array, iteratee, comparator) {
45 var index = -1,
46 length = array.length;
47
48 while (++index < length) {
49 var value = array[index],
50 current = iteratee(value);
51
52 if (current != null && (computed === undefined
53 ? current === current
54 : comparator(current, computed)
55 )) {
56 var computed = current,
57 result = value;
58 }
59 }
60 return result;
61}
62
63/** Used for built-in method references. */
64var objectProto = Object.prototype;
65
66/**
67 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
68 * of values.
69 */
70var objectToString = objectProto.toString;
71
72/** Built-in value references. */
73var Symbol = root.Symbol;
74
75/** Used to convert symbols to primitives and strings. */
76var symbolProto = Symbol ? Symbol.prototype : undefined,
77 symbolToString = Symbol ? symbolProto.toString : undefined;
78
79/**
80 * The base implementation of `_.get` without support for default values.
81 *
82 * @private
83 * @param {Object} object The object to query.
84 * @param {Array|string} path The path of the property to get.
85 * @returns {*} Returns the resolved value.
86 */
87function baseGet(object, path) {
88 path = isKey(path, object) ? [path + ''] : baseToPath(path);
89
90 var index = 0,
91 length = path.length;
92
93 while (object != null && index < length) {
94 object = object[path[index++]];
95 }
96 return (index && index == length) ? object : undefined;
97}
98
99/**
100 * The base implementation of `_.iteratee`.
101 *
102 * @private
103 * @param {*} [value=_.identity] The value to convert to an iteratee.
104 * @returns {Function} Returns the iteratee.
105 */
106function baseIteratee(value) {
107 var type = typeof value;
108 if (type == 'function') {
109 return value;
110 }
111 if (value == null) {
112 return identity;
113 }
114 if (type == 'object') {
115 return isArray(value)
116 ? baseMatchesProperty(value[0], value[1])
117 : baseMatches(value);
118 }
119 return property(value);
120}
121
122/**
123 * The base implementation of `_.matches` which doesn't clone `source`.
124 *
125 * @private
126 * @param {Object} source The object of property values to match.
127 * @returns {Function} Returns the new function.
128 */
129function baseMatches(source) {
130 var matchData = getMatchData(source);
131 if (matchData.length == 1 && matchData[0][2]) {
132 var key = matchData[0][0],
133 value = matchData[0][1];
134
135 return function(object) {
136 if (object == null) {
137 return false;
138 }
139 return object[key] === value &&
140 (value !== undefined || (key in Object(object)));
141 };
142 }
143 return function(object) {
144 return object === source || baseIsMatch(object, source, matchData);
145 };
146}
147
148/**
149 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
150 *
151 * @private
152 * @param {string} path The path of the property to get.
153 * @param {*} srcValue The value to match.
154 * @returns {Function} Returns the new function.
155 */
156function baseMatchesProperty(path, srcValue) {
157 return function(object) {
158 var objValue = get(object, path);
159 return (objValue === undefined && objValue === srcValue)
160 ? hasIn(object, path)
161 : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG);
162 };
163}
164
165/**
166 * The base implementation of `_.property` without support for deep paths.
167 *
168 * @private
169 * @param {string} key The key of the property to get.
170 * @returns {Function} Returns the new function.
171 */
172function baseProperty(key) {
173 return function(object) {
174 return object == null ? undefined : object[key];
175 };
176}
177
178/**
179 * A specialized version of `baseProperty` which supports deep paths.
180 *
181 * @private
182 * @param {Array|string} path The path of the property to get.
183 * @returns {Function} Returns the new function.
184 */
185function basePropertyDeep(path) {
186 return function(object) {
187 return baseGet(object, path);
188 };
189}
190
191/**
192 * The base implementation of `_.toPath` which only converts `value` to a
193 * path if it's not one.
194 *
195 * @private
196 * @param {*} value The value to process.
197 * @returns {Array} Returns the property path array.
198 */
199function baseToPath(value) {
200 return isArray(value) ? value : stringToPath(value);
201}
202
203/**
204 * Gets the property names, values, and compare flags of `object`.
205 *
206 * @private
207 * @param {Object} object The object to query.
208 * @returns {Array} Returns the match data of `object`.
209 */
210function getMatchData(object) {
211 var result = toPairs(object),
212 length = result.length;
213
214 while (length--) {
215 result[length][2] = isStrictComparable(result[length][1]);
216 }
217 return result;
218}
219
220/**
221 * Checks if `value` is a property name and not a property path.
222 *
223 * @private
224 * @param {*} value The value to check.
225 * @param {Object} [object] The object to query keys on.
226 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
227 */
228function isKey(value, object) {
229 if (typeof value == 'number') {
230 return true;
231 }
232 return !isArray(value) &&
233 (reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
234 (object != null && value in Object(object)));
235}
236
237/**
238 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
239 *
240 * @private
241 * @param {*} value The value to check.
242 * @returns {boolean} Returns `true` if `value` if suitable for strict
243 * equality comparisons, else `false`.
244 */
245function isStrictComparable(value) {
246 return value === value && !isObject(value);
247}
248
249/**
250 * Converts `string` to a property path array.
251 *
252 * @private
253 * @param {string} string The string to convert.
254 * @returns {Array} Returns the property path array.
255 */
256function stringToPath(string) {
257 var result = [];
258 toString(string).replace(rePropName, function(match, number, quote, string) {
259 result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
260 });
261 return result;
262}
263
264/**
265 * Checks if `value` is classified as an `Array` object.
266 *
267 * @static
268 * @memberOf _
269 * @type Function
270 * @category Lang
271 * @param {*} value The value to check.
272 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
273 * @example
274 *
275 * _.isArray([1, 2, 3]);
276 * // => true
277 *
278 * _.isArray(document.body.children);
279 * // => false
280 *
281 * _.isArray('abc');
282 * // => false
283 *
284 * _.isArray(_.noop);
285 * // => false
286 */
287var isArray = Array.isArray;
288
289/**
290 * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
291 * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
292 *
293 * @static
294 * @memberOf _
295 * @category Lang
296 * @param {*} value The value to check.
297 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
298 * @example
299 *
300 * _.isObject({});
301 * // => true
302 *
303 * _.isObject([1, 2, 3]);
304 * // => true
305 *
306 * _.isObject(_.noop);
307 * // => true
308 *
309 * _.isObject(null);
310 * // => false
311 */
312function isObject(value) {
313 var type = typeof value;
314 return !!value && (type == 'object' || type == 'function');
315}
316
317/**
318 * Checks if `value` is object-like. A value is object-like if it's not `null`
319 * and has a `typeof` result of "object".
320 *
321 * @static
322 * @memberOf _
323 * @category Lang
324 * @param {*} value The value to check.
325 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
326 * @example
327 *
328 * _.isObjectLike({});
329 * // => true
330 *
331 * _.isObjectLike([1, 2, 3]);
332 * // => true
333 *
334 * _.isObjectLike(_.noop);
335 * // => false
336 *
337 * _.isObjectLike(null);
338 * // => false
339 */
340function isObjectLike(value) {
341 return !!value && typeof value == 'object';
342}
343
344/**
345 * Checks if `value` is classified as a `Symbol` primitive or object.
346 *
347 * @static
348 * @memberOf _
349 * @category Lang
350 * @param {*} value The value to check.
351 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
352 * @example
353 *
354 * _.isSymbol(Symbol.iterator);
355 * // => true
356 *
357 * _.isSymbol('abc');
358 * // => false
359 */
360function isSymbol(value) {
361 return typeof value == 'symbol' ||
362 (isObjectLike(value) && objectToString.call(value) == symbolTag);
363}
364
365/**
366 * Checks if `value` is less than `other`.
367 *
368 * @static
369 * @memberOf _
370 * @category Lang
371 * @param {*} value The value to compare.
372 * @param {*} other The other value to compare.
373 * @returns {boolean} Returns `true` if `value` is less than `other`, else `false`.
374 * @example
375 *
376 * _.lt(1, 3);
377 * // => true
378 *
379 * _.lt(3, 3);
380 * // => false
381 *
382 * _.lt(3, 1);
383 * // => false
384 */
385function lt(value, other) {
386 return value < other;
387}
388
389/**
390 * Converts `value` to a string if it's not one. An empty string is returned
391 * for `null` and `undefined` values. The sign of `-0` is preserved.
392 *
393 * @static
394 * @memberOf _
395 * @category Lang
396 * @param {*} value The value to process.
397 * @returns {string} Returns the string.
398 * @example
399 *
400 * _.toString(null);
401 * // => ''
402 *
403 * _.toString(-0);
404 * // => '-0'
405 *
406 * _.toString([1, 2, 3]);
407 * // => '1,2,3'
408 */
409function toString(value) {
410 // Exit early for strings to avoid a performance hit in some environments.
411 if (typeof value == 'string') {
412 return value;
413 }
414 if (value == null) {
415 return '';
416 }
417 if (isSymbol(value)) {
418 return Symbol ? symbolToString.call(value) : '';
419 }
420 var result = (value + '');
421 return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
422}
423
424/**
425 * This method returns the first argument provided to it.
426 *
427 * @static
428 * @memberOf _
429 * @category Util
430 * @param {*} value Any value.
431 * @returns {*} Returns `value`.
432 * @example
433 *
434 * var object = { 'user': 'fred' };
435 *
436 * _.identity(object) === object;
437 * // => true
438 */
439function identity(value) {
440 return value;
441}
442
443/**
444 * Creates a function that returns the value at `path` of a given object.
445 *
446 * @static
447 * @memberOf _
448 * @category Util
449 * @param {Array|string} path The path of the property to get.
450 * @returns {Function} Returns the new function.
451 * @example
452 *
453 * var objects = [
454 * { 'a': { 'b': { 'c': 2 } } },
455 * { 'a': { 'b': { 'c': 1 } } }
456 * ];
457 *
458 * _.map(objects, _.property('a.b.c'));
459 * // => [2, 1]
460 *
461 * _.map(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');
462 * // => [1, 2]
463 */
464function property(path) {
465 return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
466}
467
468/**
469 * This method is like `_.min` except that it accepts `iteratee` which is
470 * invoked for each element in `array` to generate the criterion by which
471 * the value is ranked. The iteratee is invoked with one argument: (value).
472 *
473 * @static
474 * @memberOf _
475 * @category Math
476 * @param {Array} array The array to iterate over.
477 * @param {Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.
478 * @returns {*} Returns the minimum value.
479 * @example
480 *
481 * var objects = [{ 'n': 1 }, { 'n': 2 }];
482 *
483 * _.minBy(objects, function(o) { return o.n; });
484 * // => { 'n': 1 }
485 *
486 * // The `_.property` iteratee shorthand.
487 * _.minBy(objects, 'n');
488 * // => { 'n': 1 }
489 */
490function minBy(array, iteratee) {
491 return (array && array.length)
492 ? baseExtremum(array, baseIteratee(iteratee), lt)
493 : undefined;
494}
495
496module.exports = minBy;