mirror of
https://github.com/status-im/sourcecred.git
synced 2025-02-20 00:08:10 +00:00
Add MapUtil.merge
for combining maps (#794)
See the docstring for details. Test plan: Unit tests.
This commit is contained in:
parent
513820c177
commit
417265a4d4
@ -122,3 +122,27 @@ export function mapEntries<K, V, InK, InV>(
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge maps without mutating the arguments.
|
||||||
|
*
|
||||||
|
* Merges multiple maps, returning a new map which has every key from
|
||||||
|
* the source maps, with their corresponding values. None of the inputs
|
||||||
|
* are mutated. In the event that multiple maps have the same key, an
|
||||||
|
* error will be thrown.
|
||||||
|
*/
|
||||||
|
export function merge<K, V>(
|
||||||
|
maps: $ReadOnlyArray<Map<$Subtype<K>, $Subtype<V>>>
|
||||||
|
): Map<K, V> {
|
||||||
|
const result = new Map();
|
||||||
|
let updates = 0;
|
||||||
|
for (const map of maps) {
|
||||||
|
for (const [key, value] of map.entries()) {
|
||||||
|
result.set(key, value);
|
||||||
|
if (result.size !== ++updates) {
|
||||||
|
throw new Error(`Maps have duplicate key: ${String(key)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -245,4 +245,53 @@ describe("util/map", () => {
|
|||||||
expect(output).toEqual(new Map().set(11, "wat").set(12, "wat"));
|
expect(output).toEqual(new Map().set(11, "wat").set(12, "wat"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe("merge", () => {
|
||||||
|
it("combines two simple maps", () => {
|
||||||
|
const a = new Map().set("a", 1);
|
||||||
|
const b = new Map().set("b", 2);
|
||||||
|
const c = new Map().set("c", 3);
|
||||||
|
expect(MapUtil.merge([a, b, c])).toEqual(
|
||||||
|
new Map()
|
||||||
|
.set("a", 1)
|
||||||
|
.set("b", 2)
|
||||||
|
.set("c", 3)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("treats empty map as an identity", () => {
|
||||||
|
const m = new Map().set("a", 11).set("b", 22);
|
||||||
|
expect(MapUtil.merge([new Map(), m, new Map()])).toEqual(m);
|
||||||
|
});
|
||||||
|
it("errors if there are any duplicate keys", () => {
|
||||||
|
const a = new Map().set("a", null);
|
||||||
|
expect(() => MapUtil.merge([a, a])).toThrowError("duplicate key");
|
||||||
|
});
|
||||||
|
it("handles null and undefined appropriately", () => {
|
||||||
|
const a = new Map().set(undefined, undefined);
|
||||||
|
const b = new Map().set(null, null);
|
||||||
|
expect(MapUtil.merge([a, b])).toEqual(
|
||||||
|
new Map().set(undefined, undefined).set(null, null)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it("merge works on empty list", () => {
|
||||||
|
expect(MapUtil.merge([])).toEqual(new Map());
|
||||||
|
});
|
||||||
|
it("allows upcasting the type parameters", () => {
|
||||||
|
const numberMap: Map<number, number> = new Map().set(1, 2);
|
||||||
|
const stringMap: Map<string, string> = new Map().set("one", "two");
|
||||||
|
type NS = number | string;
|
||||||
|
const _unused_polyMap: Map<NS, NS> = MapUtil.merge([
|
||||||
|
numberMap,
|
||||||
|
stringMap,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it("produces expected type errors", () => {
|
||||||
|
const numberMap: Map<number, number> = new Map().set(1, 2);
|
||||||
|
const stringMap: Map<string, string> = new Map().set("one", "two");
|
||||||
|
// $ExpectFlowError
|
||||||
|
const _unused_badMap: Map<string, number> = MapUtil.merge([
|
||||||
|
numberMap,
|
||||||
|
stringMap,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user