Skip to content

Instantly share code, notes, and snippets.

@mscalora
Created February 18, 2018 00:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mscalora/f36bebe77edd85f2a4524272ca0dd273 to your computer and use it in GitHub Desktop.
Save mscalora/f36bebe77edd85f2a4524272ca0dd273 to your computer and use it in GitHub Desktop.
Case-insensitive get like lodash's _.get()
function geti (value, prop) {
if (_.isPlainObject(value)) {
if (_.isString(prop) && prop !== '') {
return geti(value, prop.split('.'));
} else if (_.isArray(prop) && prop.length) {
const key = _.toLower(prop.shift()),
val = Object.keys(value).reduce(function (a, k) {
if (a !== undefined) {
return a;
}
if (_.toLower(k) === key) {
return value[k];
}
}, undefined);
if (prop.length) {
let v = geti(val, prop);
return v === undefined ? defaultValue : v;
}
return val === undefined ? defaultValue : val;
}
}
throw new Error(`iget value argument must be an object`);
}
@natanavra
Copy link

natanavra commented Aug 2, 2019

This one does not work with array accessor... e.g. data[0]
Test before using...

Since the above solution is using lodash, here's a working implementation:

const _ = require('lodash');
const castPath = require('lodash/_castPath');
const toKey = require('lodash/_toKey');

function geti(object, path, defaultValue) {
  if (!object) return defaultValue === undefined ? null : defaultValue;

  const paths = castPath(path, object);
  const { length } = paths;
  let index = 0;

  let iterator = object;
  while (iterator != null && index < length) {
    const key = (toKey(paths[index])).toLowerCase();
    iterator = findLowercaseKey(iterator, key);
    index += 1;
  }
  return (index && index === length) ? iterator : defaultValue;
}

function findLowercaseKey(value, key) {
  return Object.keys(value).reduce((a, k) => {
    if (a !== undefined) {
      return a;
    }
    if (_.toLower(k) === key) {
      return value[k];
    }
  }, undefined);
}

module.exports = {
  geti,
};

@raphaelaleixo
Copy link

The code above is working (and helped me). But it needs a little change so it returns the right defaultValue:

return (index && index === length && iterator)
  ? iterator
  : defaultValue;

@jean343
Copy link

jean343 commented Feb 3, 2021

The above code is amazing, but it would fail in the case of geti( {did: 0,}, "did" ) because 0 == null.
Here is a working version:

const toLower = require( "lodash/toLower" );
const castPath = require( "lodash/_castPath" );
const toKey = require( "lodash/_toKey" );

module.exports = ( object, path, defaultValue ) => {
	if( !object ) return defaultValue === undefined ? null : defaultValue;

	const paths = castPath( path, object );
	const { length } = paths;
	let index = 0;

	let iterator = object;
	while( iterator !== undefined && index < length ){
		const key = (toKey( paths[index] )).toLowerCase();
		iterator = findLowercaseKey( iterator, key );
		index += 1;
	}
	return (index && index === length && iterator !== undefined) ? iterator : defaultValue;
}

const findLowercaseKey = ( value, key ) => {
	return Object.keys( value ).reduce( ( a, k ) => {
		if( a !== undefined ){
			return a;
		}
		if( toLower( k ) === key ){
			return value[k];
		}
	}, undefined );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment