patternjavascriptMinor
"Invert" a JavaScript object hash whose values are arrays to produce a new object hash with keys as the elements of those original value vectors
Viewed 0 times
invertarraysproducewhosenewthejavascriptarewithelements
Problem
Background
lodash and underscore have an
An example:
The twist
I frequently work with object hashes whose values are one-dimensional arrays (vectors). I've written a function using lodash/underscore (NB. only tested with lodash) that performs an array-aware
I'd appreciate feedback on this function.
(NB. I can't use lodash/underscore's built-in
Example use
Just to confirm that it works:
Per the original
Implementation notes
My implementation seems as brute-force as possible: it's effectively a doubly-nested loop, with the outer loop going over all input object keys and the inner loop going over the c
lodash and underscore have an
invert function that takes an object hash and converts it to a new one, which has keys as the input object's values and values as the input object's keys. As such, if the values in the input object aren't unique, this non-unique input value will, when it's a key in the output object, have as its value only one of the input object's keys.An example:
_.invert({a: 1, b: 2, c: 2})
// { 1 : "a", 2 : "c" }The twist
I frequently work with object hashes whose values are one-dimensional arrays (vectors). I've written a function using lodash/underscore (NB. only tested with lodash) that performs an array-aware
invert, whose output object has keys that are the unique elements of the input object's value vectors, and values that are the input object's keys.function arrayAwareInvert(obj) {
return _.object(_.flatten(_.map(obj, function(valVec, key) {
return valVec.map(function(val) { return [ val, key ]; });
})));
}I'd appreciate feedback on this function.
(NB. I can't use lodash/underscore's built-in
invert with an object hash with array-valued keys because the resulting object has keys which simply stringify the arrays—an output object key might be [1, 2, 3].toString(), and entirely useless.)Example use
Just to confirm that it works:
arrayAwareInvert({a: [1, 2], b: [3, 4]})
// { 1: "a", 2: "a", 3: "b", 4: "b" }Per the original
invert's behavior, if the elements of the input object's value vectors aren't unique (that is, if multiple value vectors contain the same element), the output object's value for those non-unique elements will be one of the input object keys:arrayAwareInvert({a: [1, 2], b: [3, 4, 2]})
// { 1: "a", 2: "b", 3: "b", 4: "b" } // NB: 2: "b" hereImplementation notes
My implementation seems as brute-force as possible: it's effectively a doubly-nested loop, with the outer loop going over all input object keys and the inner loop going over the c
Solution
lodash and underscore both have a
It's pretty much the functional-style equivalent of Bergi's answer.
Point is, reduce is probably what you want for this.
Edit: As Bergi points out in the comments the inner iteration could also be a reduce operation
reduce (aka "fold") function that works on objects, meaning you could also do this:function arrayAwareInvert(obj) {
return _.reduce(obj, function (result, values, key) {
_.forEach(values, function (value) { result[value] = key; });
return result;
}, {});
}It's pretty much the functional-style equivalent of Bergi's answer.
Point is, reduce is probably what you want for this.
Edit: As Bergi points out in the comments the inner iteration could also be a reduce operation
function arrayAwareInvert(obj) {
return _.reduce(obj, function (result, values, key) {
return _.reduce(values, function (result, value) {
result[value] = key;
return result;
}, result);
}, {});
}Code Snippets
function arrayAwareInvert(obj) {
return _.reduce(obj, function (result, values, key) {
_.forEach(values, function (value) { result[value] = key; });
return result;
}, {});
}function arrayAwareInvert(obj) {
return _.reduce(obj, function (result, values, key) {
return _.reduce(values, function (result, value) {
result[value] = key;
return result;
}, result);
}, {});
}Context
StackExchange Code Review Q#84951, answer score: 4
Revisions (0)
No revisions yet.