Skip to content

Instantly share code, notes, and snippets.

@dwighthouse
Last active February 24, 2016 16:58
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dwighthouse/2d373b56e0f4833903fb to your computer and use it in GitHub Desktop.
Save dwighthouse/2d373b56e0f4833903fb to your computer and use it in GitHub Desktop.
Ways to accomplish various tasks in Lo-Dash, focusing on terse-ness
// 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