Last active
April 25, 2018 21:26
-
-
Save laat/24f872d2b9304b12e84fd8f69a16dc77 to your computer and use it in GitHub Desktop.
CaseInsensitiveMap
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
import CaseInsensitiveMap from './CaseInsensitiveMap'; | |
describe('CaseInsensitiveMap', () => { | |
it('should be able to construct', () => { | |
const map: Map<string, string> = new CaseInsensitiveMap<string>(); | |
}); | |
it('should be able to construct with values', () => { | |
const map: Map<string, string> = new CaseInsensitiveMap<string>([['key', 'value'], ['key2', 'value2']]); | |
}); | |
it('has case insensitive keys', () => { | |
const map: Map<string, string> = new CaseInsensitiveMap<string>([['KEY', 'value']]); | |
expect(map.has('key')).toBeTruthy(); | |
expect(map.has('KEY')).toBeTruthy(); | |
expect(map.has('KeY')).toBeTruthy(); | |
}); | |
it('can delete case insensitive', () => { | |
const map: Map<string, string> = new CaseInsensitiveMap<string>([['KEY', 'value']]); | |
expect(map.has('key')).toBeTruthy(); | |
expect(map.delete('key')).toBeTruthy(); | |
expect(map.delete('key')).toBeFalsy(); | |
expect(map.has('key')).toBeFalsy(); | |
expect(map.has('KEY')).toBeFalsy(); | |
}); | |
it('can set/get case insensitive', () => { | |
const map: Map<string, string> = new CaseInsensitiveMap<string>(); | |
map.set('KeY', 'value'); | |
expect(map.get('key')).toEqual('value'); | |
}); | |
it('returns the original keys used. in their proper casing. keys()', () => { | |
const map: Map<string, string> = new CaseInsensitiveMap<string>(); | |
map.set('KeY', 'value'); | |
map.set('Foo', 'value'); | |
map.set('bAAr', 'value'); | |
expect(Array.from(map.keys())).toEqual(['KeY', 'Foo', 'bAAr']); | |
}); | |
it('returns the original keys used. in their proper casing. entries()', () => { | |
const map: Map<string, string> = new CaseInsensitiveMap<string>(); | |
map.set('KeY', 'value'); | |
map.set('Foo', 'value'); | |
map.set('bAAr', 'value'); | |
expect(Array.from(map.entries())).toEqual([['KeY', 'value'], ['Foo', 'value'], ['bAAr', 'value']]); | |
}); | |
it('gives the original keys in forEach()', () => { | |
const map: Map<string, string> = new CaseInsensitiveMap<string>(); | |
map.set('KeY', 'value'); | |
map.set('Foo', 'value'); | |
map.set('bAAr', 'value'); | |
let found: string[] = []; | |
map.forEach((value, key) => { | |
found.push(key); | |
}); | |
expect(found).toEqual(['KeY', 'Foo', 'bAAr']); | |
}); | |
}); |
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
export default class CaseInsensitiveMap<T> implements Map<string, T> { | |
private keyMap_: Map<string, string>; | |
private valueMap_: Map<string, T>; | |
constructor(entries?: ReadonlyArray<[string, T]>) { | |
this.keyMap_ = new Map(); | |
this.valueMap_ = new Map(); | |
if (entries) { | |
entries.forEach(([key, value]) => { | |
this.keyMap_.set(key.toLowerCase(), key); | |
this.valueMap_.set(key.toLowerCase(), value); | |
}); | |
} | |
} | |
has(key: string) { | |
return this.keyMap_.has(key.toLowerCase()); | |
} | |
set(key: string, value: T) { | |
const lKey = key.toLowerCase(); | |
if (!this.keyMap_.has(lKey)) { | |
this.keyMap_.set(lKey, key); | |
} | |
this.valueMap_.set(lKey, value); | |
return this; | |
} | |
get(key: string) { | |
const lKey = key.toLowerCase(); | |
return this.valueMap_.get(lKey); | |
} | |
delete(key: string) { | |
const lKey = key.toLowerCase(); | |
this.keyMap_.delete(lKey); | |
return this.valueMap_.delete(lKey); | |
} | |
clear() { | |
this.keyMap_.clear(); | |
this.valueMap_.clear(); | |
} | |
keys() { | |
return this.keyMap_.values(); | |
} | |
values() { | |
return this.valueMap_.values(); | |
} | |
get size() { | |
return this.keyMap_.size; | |
} | |
entries() { | |
const it = this.valueMap_.entries(); | |
const keyMap = this.keyMap_; | |
return { | |
next() { | |
const res = it.next(); | |
res.value = res.value ? [keyMap.get(res.value[0])!, res.value[1]] : res.value; | |
return res; | |
}, | |
[Symbol.iterator]() { | |
return this; | |
} | |
}; | |
} | |
[Symbol.iterator]() { | |
return this.entries(); | |
} | |
forEach(callbackfn: (value: T, key: string, map: Map<string, T>) => void, thisArg?: any) { | |
const keyMap = this.keyMap_; | |
this.valueMap_.forEach((value, key, map) => callbackfn(value, keyMap.get(key)!, this), thisArg); | |
} | |
readonly [Symbol.toStringTag] = "CaseInsensitiveMap" as "Map"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment