Last active
February 24, 2016 16:58
-
-
Save dwighthouse/2d373b56e0f4833903fb to your computer and use it in GitHub Desktop.
Ways to accomplish various tasks in Lo-Dash, focusing on terse-ness
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Lo-Dash 3.8.0 | |
// ----------------------------------------------------------------------------- | |
// Search String to Object | |
// ----------------------------------------------------------------------------- | |
// Handles many slightly malformed styles (see tests) | |
// Expects each query to be separated by '&' | |
// Expects each pair to be separated by '=' | |
_.chain(queryString) // or get the current query string: window.location.search | |
// Remove initial ? if present | |
.replace(/^\?/, '') | |
// Break up into sets of pairs | |
.split('&') | |
// Split the pairs | |
.invoke('split', '=') | |
// Pairs may only contain 0, 1, or more than 2 values | |
// First, ensure there are at least two | |
.invoke('concat', _.range(2).map(_.constant(''))) | |
// Then, ignore anything beyond the first two values per 'set of pairs' | |
.map(_.partial(_.slice, _, 0, 2)) | |
// Place all values in a single dimension array... | |
.flatten() | |
// ...so we can decode everything at once | |
.map(window.decodeURIComponent) | |
// Return the values to sets of pairs | |
.chunk(2) | |
// Turn each pair into a key and value in a single object | |
.zipObject() | |
// Remove any values that do not have a key (for patterns like ...&=1&...) | |
.omit('') | |
.value(); | |
// var tests = [ | |
// '?a=1', // => {"a":"1"} | |
// '?a=', // => {"a":""} | |
// '?=1', // => {} | |
// '?a', // => {"a":""} | |
// '?', // => {} | |
// '', // => {} | |
// 'a=1', // => {"a":"1"} | |
// '?a=1&', // => {"a":"1"} | |
// '?a=1&&', // => {"a":"1"} | |
// '?a=1&&b=2', // => {"a":"1","b":"2"} | |
// '?a=1&c&b=2', // => {"a":"1","c":"","b":"2"} | |
// '?a=1&c=&b=2', // => {"a":"1","c":"","b":"2"} | |
// '?a=1&=&b=2', // => {"a":"1","b":"2"} | |
// '?a=1&=5&b=2', // => {"a":"1","b":"2"} | |
// '?a=1=3', // => {"a":"1"} | |
// '?a=1==', // => {"a":"1"} | |
// '?a==1', // => {"a":""} | |
// '?a==1=', // => {"a":""} | |
// ]; | |
// ----------------------------------------------------------------------------- | |
// Object to Search String | |
// ----------------------------------------------------------------------------- | |
// Only handles single-depth objects | |
// To use nested objects or arrays, first encode those values to strings | |
_.chain(obj) | |
// Break the object down into arrays containing a key and value in each | |
.pairs() | |
// Make the pairs into a single array | |
.flatten() | |
// Ensure they are all string values by using String constructor | |
.mapValues(String) | |
// Encode the strings | |
.map(window.encodeURIComponent) | |
.invoke('replace', /[!'()]/g, window.escape) | |
.invoke('replace', /\*/g, '%2A') | |
// Pair up the values again | |
.chunk(2) | |
// Join the pairs | |
.invoke('join', '=') | |
// Join all the sets of former pairs | |
.join('&') | |
// Replace the whole string with itself plus a leading '?' | |
.replace(/(^.+$)/, '?$1') | |
.value(); | |
// var tests = [ | |
// {a: void 0}, // => "?a=undefined" | |
// {a: null}, // => "?a=null" | |
// {a: 1}, // => "?a=1" | |
// {a: 'b'}, // => "?a=b" | |
// {a: _.noop}, // => "?a=function%20noop%28%29%20%7B%0A%20%20%20%20%20%20%2F%2F%20No%20operation%20performed.%0A%20%20%20%20%7D" | |
// {a: {b: 1}}, // => "?a=%5Bobject%20Object%5D" | |
// {a: 1, b: '2'}, // => "?a=1&b=2" | |
// {a: 1, b: '?a=1&b="?a=1&b=2"'}, // => "?a=1&b=%3Fa%3D1%26b%3D%22%3Fa%3D1%26b%3D2%22" | |
// ]; | |
// Lo-Dash 2.4.1 | |
// Copy unique fields from source into destination, ignore shared fields | |
_.each(_.difference(_.keys(source), _.keys(destination)), function(uniqueKey) { | |
destination[uniqueKey] = source[uniqueKey]; | |
}); | |
// Shorter way to do the same thing | |
_.merge(destination, _.omit(source, _.keys(destination))); | |
// This is almost the same thing as _.defaults | |
// Difference: _.defaults will make source overwrite destination fields value is undefined | |
_.defaults(destination, source); | |
// Create an array excluding the element excep at an index (like _.reject, but with array indices) | |
var arrayWithoutValueFromIndex = _.first(sourceArray, index).concat(_.rest(sourceArray, index + 1)) | |
// The opposite of this is _.at, which returns an array with only the specified index element | |
var arrayWithValueFromIndex = _.at(sourceArray, index); | |
// Validation helper: If your object's validity is represented with like: | |
// var myValidityCheckResults = { | |
// firstThingIsValid: true, | |
// secondThingIsValid: false, | |
// thirdThingIsValid: true | |
// } | |
// Then the validity of all can be determined with a single line | |
// If any one of the results is false, allValid will be false | |
// If the object is empty, allValid will be true | |
var allValid = _.every(myValidityCheckResults); | |
// Validation helper: If you wish to check validity of each object in a list of objects: | |
// var myObjects = [ | |
// { | |
// name: 'something1', | |
// _valid: { | |
// firstThingIsValid: true, | |
// secondThingIsValid: false, | |
// thirdThingIsValid: true | |
// } | |
// }, | |
// { | |
// name: 'something2', | |
// _valid: { | |
// firstThingIsValid: true, | |
// secondThingIsValid: true, | |
// thirdThingIsValid: true | |
// } | |
// } | |
// ] | |
// Then the validity of all can be determined with a single line | |
// If any one of the results in any of the objects is false, allValid will be false | |
// If the array is empty, allValid will be true | |
// Any empty _valid object will count as valid | |
var allValid = _.chain(myObjects).pluck('_valid').map(_.values).flatten().every().value(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment